views:

111

answers:

5

I'm trying to retrofit some tests using Test::More to legacy code and I've bumped into a bit of a snag. I don't seem to be able to set %ENV in the test module. The called function definitely uses this variable so %ENV doesn't seem to be carried across to the test object.

#!/usr/bin/perl

use strict; use warnings;
use Test::More qw(no_plan);

BEGIN {
    $ENV{HTTP_WWW_AUTHENTICATE} = 
        'WWW-Authenticate: MyType realm="MyRealm",userid="123",password="abc"';
    use_ok('Util');
}

$ENV{HTTP_WWW_AUTHENTICATE} = 
    'WWW-Authenticate: MyType realm="MyRealm",userid="123",password="abc"';

printf qq{get_authentication_info = "%s"\n}, get_authentication_info();
ok(get_authentication_info(), 'Get authentication info');

I keep getting...

perl t\Util.t
ok 1 - use Util;
Use of uninitialized value in concatenation (.) or string at t\Util.t line 14.
get_authentication_info = ""

As with all things Perl, I'm pretty sure that some one has done this before.

UPDATE: Thanks to all for your help

The problem was between the keyboard & chair ... My test data was just plain wrong It needed to be

$ENV{HTTP_WWW_AUTHENTICATE} = 
    'MyType realm="MyRealm",userid="123",password="abc"';
+2  A: 

Why are the lines setting $ENV{HTTP_WWW_AUTHENTICATE} commented out?

Also, what are the specs for get_authentication_info()?

Sinan Ünür
This is demo code... the comments just show where I tried setting the %ENV hash.
telesphore4
Setting `$ENV{HTTP_WWW_AUTHENTICATE}` worked just find when I tried it, you must be doing something else wrong.
Lukáš Lalinský
@telesphore4: Well, don't post commented out code. Post the code you actually try to run instead of relying on others' capacity to deduce what you are or are not doing. If I had to guess, I would say the problem is in `get_authentication_info()`.
Sinan Ünür
You were able to access the test code in the test module? If so, then please post your test code.
telesphore4
@telesphore4: I think you got this wrong: You need to show more information.
Sinan Ünür
Last comment is correct. Thank you. I tried reducing the client code and found a problem in the test. Accepted because you stuck to your guns on the telesphore4 has messed something else up
telesphore4
+4  A: 

As Sinan said, the $ENV{...} lines are commented out, so it can't work. But if you want really testable code, I'd suggest to make the get_authentication_info function take a hash as an argument. That way you can test it without setting the global variable, and in the real code you can pass the real enviromnent hash. Global state will always become a problem eventually.

Lukáš Lalinský
As I said this it legacy code so this is going to be a problem all over
telesphore4
As long as it's legacy code under your control, you can always refactor it.
Lukáš Lalinský
True, but I'm trying to do the "tests before changes" TDD thing
telesphore4
Sometimes you have to refactor your code before you can adequately test it. IMO it's one of the best things about TDD: it forces you to think carefully about the architecture of your code and write things modularly. :)
Ether
+2  A: 

Agreed with Lukáš -- get your global environment (and perform validity checks etc) all in one place, such as in its own method, and then pass those values to all other methods that need it. That way in your unit tests you can just drop in a replacement method that determines the environment and config variables in a different way (such as from a file, or directly set at the top of your test script).

Ether
This is legacy code
telesphore4
+1  A: 

Try setting the env variable before BEGIN.

If not try this:

  1. First, go to a command prompt and set the env var there. Then run your script. If the tests pass. Then as you predicted, the problem is with setting the env var.

  2. If the tests fail, then the problem lies some where else (probably in get_authentication_info).

Thushan
I tried the literal "before the BEGIN block> No good. Perl executes the BEGIN block before anything else... so where would I put that exactly.
telesphore4
Yes, BEGIN is executed before other code, but I was guessing maybe it's executed in a different context so the env var doesn't survive after BEGIN execution. But obviously I was wrong. :)I added simple plan to test your code. Did you try it?
Thushan
+2  A: 

What does

get_authentication_info()

return?

My guess is nothing.

If this is always true, then line 14 will always return the "Use of uninitialized value..." warning.

If you expect a value, you need to investigate why get_authentication_info() is failing?

David Harris
Not exactly but close enuf to get me on the right track
telesphore4
So what happened exactly? don't leave us in the dark!
Ether