Re: How to make a module aware it is being tested?
by dragonchild (Archbishop) on Nov 01, 2007 at 23:50 UTC
|
In general, you use an environment variable for this kind of behavior. I would strongly urge against it because that kinda negates the point of being tested. It sounds like you have an XY problem. You probably want to use some sort of mock object instead of having the module provide the mocking.
My criteria for good software:
- Does it work?
- Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
| [reply] |
|
|
As I explained above, the tests will remain the same, it is just the test-data to be inserted in the database that needs to be "manipulated" so they do not interfere with the real data. As the data are parsed out of external files I cannot change (since that would defeat the testing of the parsing routines) I thought it was a good idea to change some fields after the parsing but before the insertion. On second thought and as suggested elsewhere a testing database would solve all those problems nicely.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James
| [reply] |
Re: How to make a module aware it is being tested?
by GrandFather (Saint) on Nov 01, 2007 at 21:51 UTC
|
Sprinkle if (exists $INC{'Test/More.pm'}) (or whatever test module you are using) tests through your code as required.
That doesn't tell you if the code was actually called in a test context, but it does tell you if the test environment is loaded.
Perl is environmentally friendly - it saves trees
| [reply] [d/l] |
|
|
Seems like it would be a little more straightforward to test for one of the testing package's variables, like
if ($Test::VERSION)
Caution: Contents may have been coded under pressure.
| [reply] [d/l] |
Re: How to make a module aware it is being tested?
by gamache (Friar) on Nov 01, 2007 at 21:20 UTC
|
| [reply] |
|
|
| [reply] |
|
|
The module will have to work with an active / life database and the records to be inserted are parsed from real life example files which I cannot change.
Setting up a database for testing
by copying a few records from the live database sounds like a better idea.
| [reply] |
|
|
Re: How to make a module aware it is being tested?
by KurtSchwind (Chaplain) on Nov 02, 2007 at 00:27 UTC
|
| [reply] |
|
|
You really don't want to push that out to prod and end up with test crap in your database. All too true, hence my initial idea to have the module check whether it was being tested or not. When in testing mode it would insert data records with a clearly identifiable "TEST" mark which would be easy to remove even if the test totally crashed and did not clean-up at the end. But I'm now convinced that a test database is probably the better choice.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James
| [reply] |
Re: How to make a module aware it is being tested?
by brian_d_foy (Abbot) on Nov 02, 2007 at 23:13 UTC
|
What was theuse case that you had where this would be useful? This sound a bit like an XY Problem.
Were you setting variables to different configuration values or something like that? Are you trying to mock a function? There's probably a much more robust way to accomplish your goal that doesn't involve magic or fragile code such as checking for a particular module. If you need to do this, the trick is to be able to control it yourself and not depend on something you can't control.
A case I have is credit card processing. I have a program that can charge a credit card. In the `make test` step of development, I don't want to charge the card. However, in deploying it, I also want to do a human test without charging the card. One of these test situations is under the test harness framework, and one isn't.
I use an environment variable. If I set the environment variable specifically tailored to my script (TEST_PROGRAM_NAME, for instance), which I can do in a program file or on the command line, my program can recognize the test condition with something I know that only I am affecting, I don't have to figure out acrobatics. Also, In my test harness stuff, I can turn the environment variable on and off, either in separate test scripts or even the same test script.
However, I can also do that with a configuration directive. I turn off or on features I need in the normal pogram configuration. That way I can change how the program acts without the test scripts having to invoke a magic environment variable to change behavior.
Another case I have is using the right database. In a test situation I have to hit a test database and in production I have to hit another. That's usually a matter of having the right configuration hooks. Inside the test situation though, often I want to test things that don't need the database, but at the semi-integration testing level I want to invoke the application, and the application wants to talk to the database. There I'll use some sort of Mock DBI object that pretends to connect to the database (and probably mocks returning the right data for particular calls). This is the same sort of thing I wold do if I needed my application to talk to the network, but I want to test it offline.
I don't want to recommend anything in particular without knowing what you are trying to accomplish, though. As with all program design problem, the trick is to reduce special cases. :)
And, finally, if your module acts differently under test conditions, how are you going to test how it acts not under test conditions? :)
| [reply] |
|
|
My use case is as follows:I get external files which I need to parse to extract the data I have to save into a database. I cannot change these external files as that would invalidate the testing of the whole parsing process. The next step is to save this data into the database, BUT - The database is live; and
- the testing process might crash and fail to clean-up the data it inserted during testing.
Hence my idea to change the primary keys of the data to be inserted, so - the other programs using the database recognize the data as test-data and will not use them; and
- it is easy to manually delete the inserted test-data in case the test script crashed and failed to clean-up.
For that to work I had thought it would be easiest if my module would "know" when it was being tested, so it could manipulate the test data as explained above. Rather than relying on environment variables, external semaphore files or additional attributes on the module's object (all of which a programmer might forget to set or provide), I was looking for a solution which could be built-in, but it seems there is no easy fool-proof automatic way to check if a module is being "tested".
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James
| [reply] |