Java – Setting up an automated testing framework with Selenium

Architecturejavaseleniumtestingwebdriver

I am working on large websites that get updated (new features added, content changed, etc.) at least once a week. testing however, if at all present, is never as thorough as it should be. so a week ago i started looking into automated testing and selenium.

I read that if you wanna do it right, dont rely solely on selenium ide. programming your tests offers a lot more options. i wasn't comfortable with the third party PHP bindings at all so i quickly skipped to using java for programming the tests.

Now my question revolves around how to cleverly setup the system that will be running the tests. my idea was the following:

  • the tests will/should be totally autonomous
  • nevertheless i want to have some kind of main application to loop all these tests and run them one after another
  • the main application should be running 24/7 or at least get started periodically by a cronjob or something
  • tests should be run in as much browsers (or simulated clients??) as possible. so far i'm using FF, IE and chrome through their respective WebDrivers.
  • I wanna name some folder and collect all the tests in that folder. the main application will then just take whatever is in that folder and run it. then everybody will just create their tests and put them in that folder, so they'll get added to the queue
  • it would be nice to have a way to create tests with selenium ide, export them and they immediately work with my main application (i.e. they get run correctly without any modifications needed). ok, i know i said, selenium ide is disadvised but i feel it's a good start for some simple tests. also, people without any programming knowledge can still use it. as it is right now, i'm exporting the tests created with selenium ide as "Java / JUnit 4 / WebDriver" and changing a little bit of code (passing a WebDriver obect as a parameter).

Here is the code for my "main application":

import java.io.File;
import java.io.FilenameFilter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.WebDriver;

public class SeleniumTest {

    public static void main(String[] args) throws 
    ClassNotFoundException, InstantiationException,IllegalAccessException, 
    NoSuchMethodException, SecurityException, IllegalArgumentException, 
    InvocationTargetException {
        String[] drivers = {
                "org.openqa.selenium.firefox.FirefoxDriver",
                "org.openqa.selenium.ie.InternetExplorerDriver",
                "org.openqa.selenium.chrome.ChromeDriver"
        };
        Class params[] = {WebDriver.class};
        String testFolderName = "lookhere";

        while (true) {
            //get all .java files from some folder. those will be the tests to run
            File testFolder = new File(testFolderName);
            FilenameFilter filter = new FilenameFilter() {
                public boolean accept(File dir, String name) {
                    return name.endsWith(".java");
                }
            };
            String[] tests = testFolder.list(filter);
            if (tests == null) {
                System.exit(0);
            }

            for(int i=0; i<drivers.length; i++) {
                //loop through different drivers, instantiate them
                Class webDriverClass = Class.forName(drivers[i]);
                WebDriver driver = (WebDriver) webDriverClass.newInstance();
                driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

                for (int j=0; j<tests.length; j++) {
                    //loop through tests, instantiate them
                    String currentTestName = tests[j].replace(".java", "");
                    Class testClass = Class.forName(currentTestName);
                    Object test = testClass.newInstance();

                    Method methods[] = testClass.getDeclaredMethods();
                    Method fn;

                    //run every method that starts with "test" (usually just one)
                    //also run setUp, passing the driver object
                    for(int k=0; k<methods.length; k++) {
                        if (methods[k].getName().startsWith("test")) {
                            fn = testClass.getDeclaredMethod(methods[k].getName());
                            fn.invoke(test);
                        } else if(methods[k].getName().equals("setUp")) {
                            fn = testClass.getDeclaredMethod("setUp", params);
                            fn.invoke(test, driver);
                        }
                    }
                }

                driver.quit();
            }
        }
    }
}

As you can probably see, i am not at all an expert at java, so dont be put off by bad form (like the long throws-declaration of the main method).

Now, for my questions:

  1. is my entire concept, that i formulated above, okay? that is: having a main application run all the tests and a queue to which i can add/remove tests on the fly. or are there other methods of best practice regarding this? what other concept/architecture can you think of?
  2. is there a way to create tests with selenium ide, export them and they immediately work with the main application without any modification needed?
  3. ok since i posted code, you probably wanna go crazy and criticize that 😉 i'm open for all kinds of suggestions.
  4. is it possible with selenium to run different versions of IE (or any browser, for that matter) ? it probably just runs the browser version that i have installed. so if i wanna test different versions of one browser, i have to call remote machines which means selenium grid? i'm really just guessing right now 🙂

Best Answer

I would use TestNG to orchestrate tests instead of a main method, it allows for parameterisation as the previous answer states, and if you use selenium GRID 2, you can run tests in parallel and on many different browser/OS version combo's

I would also consider modeling test cases using PageObjects & PageFactories, this will further help in making tests encapsulated and robust.