There are multiple advantages of doing this:
- We could run these Selenium tests on our Continuous Integration server (Hudson in our case) as part of build process. This means, if because of some check-in, a selenium tests fails, the build fails and hence someone has to fix it!
- Developers and QA's can easily run these functional tests whenever they want. For e.g. if developers want to make sure that the code they are about to checkin does not break any existing functionality they can run the functional tests before checkin with just one command.
Lets try and reverse engineer the problem. To run selenium tests we need to do the following things
- Compile the app
- Run unit-tests
- Create a war file of the application
- Run an tomcat server (or any other servlet container you are using)
- Deploy the war file created in step 3 on the server started in step 4
- Start the selenium server
- Fire the selenium tests
Lets do this step-by-step:
Lets break down the problem. If you look at the above mentioned 7 steps. We can classify them in four broad categories
- Compile the application and package it as a war file. (steps 1-3)
- Run the tomcat server (steps 4-5)
- Run the selenium server (step 6)
- Run the selenium tests (steps 7-8)
Solving the step 1:
Assuming that you already have the pom.xml setup to properly compile and run unit-tests. We need to add the configuration in pom.xml to package the application as war file. This is what we have to do
Find the tag called <packaging> in pom.xml and set the value of the tag to war instead of jar.
Then, we need to tell maven about how the war file will be generated. This is done using the maven-war-plugin. The sample configuration looks like this:
Of course for all this to work you should have a proper directory structure and web.xml. But I will assume that you already have that in place.
At this point if you run the following command:
You will get a war file ready to be deployed in any servlet container.
Next, Solving the step 2:
To run an embedded tomcat server we have to add the following configuration to pom.xml
Now, when we run the following command, we will have a running tomcat server with our application deployed on it.
Next, Solving the step 3:
To start the selenium server from command prompt we need to do two things.
- Add the dependency of selenium drivers to the app. This is required so that we could use selenium api to programmatically write selenium tests. This is done using the following code:
- Add the selenium plug-in so that we can start the selenium server from the command prompt. This is done using the following code:
After this we can start the selenium server using the following command:
Next, Solving the step 4:
Now, we are ready to run the tests simply run the tests using the following command:
We have our selenium tests running as part of our maven build! To do this we have to fire three commands from three command prompts/terminal windows. One running tomcat, another running selenium server and the third running the tests.
All this is good but we don't want three command prompts running. We just want one command that does it all!
And this is exactly what we are going to see next!
So as you already know that Maven is build around phases, we are going to run our functional tests (selenium tests) in the integration-test phase.
- Start the tomcat server
- Deploy the war
- Start the selenium server
- Fire the function tests
Above configuration means that following things in plain english:
- Start the tomcat6 server
- Deploy the app during the pre-integration-test phase.
- Stop the server during the post-integration-test phase.
Next up, Step 3 do this:
Above configuration states the following:
- Start the selenium server during the pre-integration-test.
- Stop the server during the post-integration-test.
To run the functional tests during the integration-test phase, do the following (I promise this is the last bit of XML that you see on this post!)
This configuration does the following:
- Tells maven-surefire-plugin to run the unit tests during the test phase but exclude the classes in the functional folder.
- Run the test class in the functional folder during the integration-test phase.
- Application will compile
- Unit tests will run
- War file will be created
- Tomcat server will be started
- war file will be deployed on the tomcat started in step 4
- Selenium server will be started
- Functional tests will be fired
- And we will live happily ever after!