Thursday, April 19, 2007

Test your web application with Selenium

Thanks to Skills Matter I attended a Selenium session tonight. Selenium is a tool for automated web testing. The session was led by Erik Doernenburg. He's a ThoughtWorker, so I knew the presentation was going to be good quality. Not only did he present what Selenium is, but he also presented many good techniques for using it with your project.
Some of my notes below:
  • All important browsers are supported
  • All important languages are supported
    • He used Java at the talk
  • SeleniumIDE is the tool for recording tests
    • It's not necessary to use it, you can write tests in your favourite language
    • SeleniumIDE is only for Firefox
  • You need to start the Selenium server in order to run tests
  • Many methods available:
    • createCookie
    • dragdrop
    • fireEvent
    • selenium.click("btnG")
    • assertTitle
  • There is a concept of locators
    • It means the way to locate your DOM elements
    • name, id, identifier
    • document.forms['myForm'].myDropDown
    • XPath
    • link text
    • css selectors, css = a[href="#id3"]
  • Selenium server sets the proxy in your browser, so your browser asks the server for everything
  • It's bad for performance testing
  • Good for testing multiple browsers
  • There was some great advice, which I think applies for all kinds of functional tests
    • "Test what you want to test"
    • Which means, if you have already tested creating users in a functional way, you don't need to test it functionally again
    • So, you can actually use your production code to change the state and then functionally test what you're actually testing
    • Saves time
    • Makes your tests less fragile
    • Cool!
  • It's a good pattern to have classes for all of your pages
    • WelcomePage
    • DailyViewPage
  • And one class for your test
    • AddItemToBasket
    • CreateUser
  • Your test classes will then use your page classes
    • welcomePage = WelcomePage()
    • welcomePage.setDailyView()
  • There are other ways of functionally testing your web application
    • HttpUnit which asks your web server, not the browser
    • Use a Presentation pattern
      • have only thin presentation layer
      • test only your "event handlers" methods
  • It's common practice for QA people to create Selenium scenarios
  • You can start your TDD session with a failing Selenium test

5 comments:

LuizGeron said...
This comment has been removed by the author.
LuizGeron said...

Selenium is pretty cool, but has some problems too. Despite some alternative ways of running it, selenium doesn't really support testing applications that use multiple domains (like in my case, one specific for authentication) or mixing http and https urls in the same testing session.

Tartley said...

I've used it for testing performance with no problems. But the web application I was testing was taking up to 2 minutes to return a page when I started, so perhaps the problems Erik referred to are simply due to the jitter in timings produced by the selenium overhead, which might affect faster pages?

I tried to use it for load testing as well, by firing off several sessions simultaneously from the command line, but I never got that to work. I suspect the outgoing simulteneous http connections from a single Windows machine are throttled to about 4.

poulwiel said...

"Which means, if you have already tested creating users in a functional way, you don't need to test it functionally again" - what do You mean by that? Is it related only to rails?
As i understand it, i should not test things i have tested in unit tests, for example accurate tax amount on invoice.

Andrzej Krzywda said...

Hi Poulwiel,

The idea isn't Rails-only.
If you want to test that a user is able to create new bills you don't need to use Selenium to log in as this user. You probably have already tested that in another functional test. Instead, you can prepare the state (a user already logged in) using your internal object structure.

For me, the main goal of a functional test is to simulate a user's behavior. I always try to have 100% unit test coverage, which means I'll probably have some duplication in my functional and unit tests.