2011-04-13

Automated Web Testing with Selenium and The NetBeans Rich Client Platform

I developed tooling for work I do for Scripps which helps me create Selenium based automated user tests more easily. These are not open source at this time, though that may be possible some day. I might use the ones I have created as an example to make some better for OSS since I have learned lessons along the way.

This tooling has been built on the NetBeans Rich Client Platform, but too, will run right in the IDE. I show IDE examples in this post. It helps create Java projects for using Selenium for automated user testing. This ties in nicely with the IDE.

There are different technologies supported in the tooling. There is a JavaScript runner or window which allows one to run JavaScript inside Selenium using runScript and getEval. Too, there is project support for Java and Groovy. I don't show the Groovy support here, but it is exactly the same as the Java examples less you will be using a Groovy file instead of a Java file, so you can derive how it works from that.

This is not the same as the tooling available in the current NetBeans auto update centers. I noticed it when I started this, and I don't see that it addresses things in the same manner which I do. I don't focus on the tests in this case as much as I focus on being able to test chunks of code as you are trying to develop the logic which will exercise your application.

The reason I do this is because I do not just write tests. I create automation APIs which can be used to affect the system. This then allows tests to be created using those APIs. That limits the impact of application changes to the high level test scripts which use the APIs I create. Thus, if a change occurs in the application which can break the tests, then I change one file versus many.

The above may be a topic of another post one day. I will now get on with showing the tooling.

First, and not really shown here, I needed a way to proxy calls to a Selenium session. I created a library which implements certain aspects of Selenium to allow this to happen. This simply gets and sets the Selenium session ID so calls for a Selenium session may come from multiple places. In this case, the user serializes those things. You will see it references in code which follows.

Next, I needed a way to manage Selenium server connections, and too I needed a simple way to kick off a Selenium server in the development environment. The "Selenium Manager" top component handles this for me. Certain aspects are configurable.





You can also start and stop the in IDE Selenium server here. The output uses the NetBeans output window for this.



Once you have configured connections, you can start and use them one at a time


Once a live session is available, the manager allows you to stop it or to copy the session ID using context menus


Next, and most importantly, there is the ability to do productive things.

There is a Selenium JavaScript runner. This is a special window where one can type in JavaScript, execute it, and see the response. Too, one can ask for the current HTML from the page based on the DOM and not the plain HTML sources before any JavaScript logic has applied changes.


Notice the syntax highlighting options in the output below. I suppose I could add the ability to view that as JSON too. This is an example of using the "Grab HTML" button



Notice the part above dealing with ret=ret in the JavaScript image. This is due to the way this logic will be run directly in Selenium and the way it returns the last evaluation instead of having the caller use the return statement; this is a Selenium thing (see Selenium.getEval). That could have been worked around in the JavaScript runner if I had put the logic in a function and called it, but for the purposes of using this window that is a little overhead I don't need.

Above, you may have noticed the use of jQuery. How did it get there? Right, there is a difference in the JavaScript used in your application, and that used in Selenium. You can see my other blog post for more information, but I injected jQuery into the current Selenium session using Selenium.addScript from some Java code.

I will show you how that gets there in a bit.

It should be obvious we are using the started session here, but just to be clear, before I can run this JavaScript, I had to start a Selenium session and drive the state of the browser manually to get to what I wanted to operate against. In this case not really as the session opened on the Google home page.

Above, I mentioned injecting jQuery. Well, if you can inject jQuery, then you can inject your own JavaScript as well. You can take the logic you figure out in the JavaScript runner and move that into your own JavaScript files which you will inject.



Next, you can create a regular Java project in the NetBeans IDE. Then, you can create a standard Java class. You can then click on a line in the Java file and bring up a context menu and ask the tooling to inject the required Selenium proxy logic to allow you to write code using the current session.


This can be in a main method as above in which case it will be a local variable, or it can be at the class level. Repeated uses of the above action will just overwrite the previously injected code unless it is deleted; in that case it will be added back. This is needed if you stop the Selenium session and restart it. In this case you get a new session ID. Once you use the action, your class will look like this


Then you fill in some scratch pad type code to exercise some logic you will later add to an actual API. This may seem counter intuitive, but the point is to be able to drive the state of the application with the browser while you write some finite pieces of the whole which you know work. This greatly reduces the time to get the state in place and start the test etc. The develop test cycle becomes easier to manage.



So, how did our JavaScript and jQuery come to reside in the Selenium session? It was put there with another scratch pad Java class.


The related libraries were added to my Java project automatically for me by the tooling too. This includes the proxy library which I first wrote about.


I'm obviously trying to use a very simple example here. To get real work from these tools I have a full blown AUT API I have designed and developed for the project I'm testing. Too, I have developed the infrastructure needed to use the API including a set of tests and Ant build scripts.

The individual tests I can run directly from the IDE as they are JUnit tests, and their core logic can be developed, along with the APIs, running against a live Selenium session. The Selenium JavaScript injection is done automatically by my base JUnit test along with other preliminary things.

Hopefully at some point in the near future I will create an OSS version of this tooling. I don't have an ETA at this moment. But, I hope as I feel it could be useful for many.

1 comment:

Jonas said...

Impressive! Let me know when you release it! :D