“Inversion of control” and “dependency injection” are the 2 terms you can research for more information on this topic. I am going to talk in layman terms, only, as to why I think software test automation developers (or all developers) should be aware of this techniques. It is another very useful tool for your toolbox.
My first experience with IOC and dependency injection was with java, using the Spring framework a while back. More recently I have used Spring.NET, the .NET version of Spring. I am currently using Spring.NET and Unity, although there are many flavours of IOC containers out there.
For those of you who don’t have a clue what I am talking about, imagine a washing machine and a dishwasher. They both do the same job, washing, but go about it in very different ways. Although the idea of a combo washer/dishwasher has been patented, it is highly likely that for the foreseeable future we require 2 machines. They even have very similar user instructions,
- Load machine
- Insert detergent
- Select program
- Press Start
Imagine that you indeed had 1 machine that was a washer / dishwasher combo. Imagine that the hardware for the machine was sufficient for all types of washing. Imagine the machine had a card slot that accepted a card that had the software to execute for the type of washing you wanted to do. You inserted the “Dishwasher” card into the slot and the machine washed dishes. You didn’t care how it worked or what was under the shell, you just washed clothes and dishes according to the card you put in the machine. In a years time a new card came out for your machine that allowed it to wash small pets; No more taking your Chihuahua to the grooming parlour once a month. Put the new card in the machine, pop your dog in and hey presto, your beautifully clean, although mentally scarred, best friend appears 30 minutes later. That is inversion of control. The machine supplies the rules of how to wash and any implementation that follows the machines rules may be implemented as a new “card”. You configure the machine (put the card in) and it goes off and gets the implementation to execute.
So IOC, in my mind, is the idea of decoupling rules from implementation. Dependency injection provides one way to enable this. Hopefully you can already see how this may be useful to you. Let me now give you a more concrete example.
In my series Create Test Automation Framework I show how to create an automated test framework from the ground up. Currently it uses QTP as the test tool, or “engine”. In a future series I am going to modify the test application I provided for the above series to allow users to run the same tests against different “engines”.
Say your company had API, UI and database tests. These tests may target the same functionality, but the type of testing is different for each.
If you adopted a test language for your company then you could use the same language to execute tests using different engines,
The above steps all use QTP (4th column). So all steps are executed as UI test steps. If you changed column 4 in step 2 and 3 to API then these steps would be run as API test steps. We use the same language, but our configuration (API, UI, DB) tells the application what “engine” to use. IOC and dependency injection make this easy.
There are various types of dependency injection and I tend to prefer interface injection. It lends itself very well to unit testing and mocks in particular.
So the test language defines the rules by way of providing interfaces. Each engine that comes along implements functionality according to the provided interfaces. This would also mean you are not tied to a specific implementation. If your company suddenly decided that QTP was no longer the UI tool of choice, you would create a new assembly with your newly adopted UI tool, update the configuration files to point to the new assembly and away you go.
Hopefully that's enough to illustrate that these techniques are worth knowing and can provide huge benefit to not only software development projects, but software test automation efforts as well.