PHPUnit and global variables
April 30, 2008The first time I did some work with PHPUnit I was writing out tests in preparation for some refactoring. So I put together a bunch of tests for my utility classes, and pure logic classes etc, database access classes, etc. So everything was trucking along wonderfully, things are falling into place and then I run a test that tests some database stuff.
The application was setup with a configuration file that defined all of the database connection information, this file is included by the database library providing a single set of database routines to be shared by the application. Pretty standard stuff here. Perhaps in a nod to the rails/java crowds it could have been put in a non-code file and read in by the application but as far as I’m concerned that’s just personal preference. At some point you’ve got to have some configuration information somewhere and this works as well as anything.
So now that you know how things were setup, we’re back to the PHPUnit test…it bombed, failed, crashed, whatever. After digging into it a bit I discovered that PHPUnit has a problem with munging the global namespace when it runs. Things that are global variables can’t be pulled down into local scope because they don’t exist there anymore. I did some reading and found numerous complaints about this in the PHPUnit bug system, all of them closed with “this issue resolved” when the issue most assuredly had not been solved. I even found a conversation where one of the developers stated that it was not a bug, that the user simply needed to modify their code to work with PHPUnit. Huh? Modify the architecture of your code to work with a testing framework?!?
I spent some time thinking about this and I think it could be said that he’s right, but for the wrong reasons. First off, if this is a technical limitation of PHP then just say so and let it go. If it’s an implementation problem with PHPUnit then say so and try to put together plans to fix it. However, I think in this particular instance the problems that I was experiencing with PHPUnit could indicate a larger problem in my application.
Here’s how..One of the things that I hated when I first started using PHP was having to pull things out of the global namespace into the local namespace to use them. When PHP5 came out and the object model finally had a good amount of maturity I moved to utilizing classes for most of my code and this allowed me to start using the $this operator for accessing a lot of variables that I needed to deal with. In fact, the only place I was really using globals was in my library routines. After thinking about this for a bit I realized that it was much more convenient to wrap all of the configuration data into Singleton then I’d have a single object that I could use to get all data instead of having to pull in everything I needed one variable at a time.
It was at that moment that I realized if I had a singleton that housed all of the configuration data I could instantiate it in all of the routines where I needed to access configuration data and it would avoid the problems that PHPUnit had with the global namespace. When I looked in the todo’s for the configuration file there was an item at the top “Maybe I should turn this into a singleton”…two birds with one stone? Ten minutes of work and I had everything setup and ran my tests and “bingo” everything worked.
So in the end, modifying the way that configuration information is disseminated throughout the system by using a singleton has been “the right thing”. I had some heartache over the responses from the PHPUnit developers about the “solution” to the problem their users were having mostly because the solution involved a lot of extra crap with addressing the global namespace in a particular way. Using a singleton ended up providing the needed functionality, didn’t do anything retarded with variable access, and ended up making the application much cleaner to work with.






