Closing Browser After Failed Test

23,721

You haven't mentioned what framework you're using for executing your tests, but one way to handle this would be to use the equivalent of an "after test" annotation to accomplish this. JUnit calls this annotation @After while TestNG calls it @AfterMethod. The method annotated with the after test annotation will run after each method annotated with @Test, regardless of the pass/fail state of the test. If you are expecting to use the same driver instance across test methods, most test runners have an @AfterClass annotation or similar, which will run at the end of all @Test methods in the class.

As an example, you'd want to do something like the following (note the promotion of the driver variable to a member variable in the class):

public class ClickAddMedication 
{
    // N.B. For this approach to work, you *must* have the "driver"
    // variable here. Having it as a member variable of the class is
    // what allows the addMedication() method to access it for manipulating
    // the browser, and the tearDown() method to access it for closing
    // the *same* *browser* *instance*.
    WebDriver driver;
    Browser browser = new Browser();

    public void addMedication(String driverName)
    {
        //Open Browser and navigate to page
        driver = browser.getDriver(driverName);
        driver.manage().window().maximize();
        driver.get("http://someIP:8080/hmp_patient/index.html");

        //Click Add Medication button
        WebElement addBtn = driver.findElement(By.id("add-btn"));
        addBtn.click();

        //Verify Add Medication page has loaded successfully
        WebElement rxBtn = driver.findElement(By.className("icon-rx"));
        WebElement otcBtn = driver.findElement(By.className("icon-otc"));
        WebElement herbBtn = driver.findElement(By.className("icon-herb"));

        Assert.assertEquals(true, rxBtn.isDisplayed());
        Assert.assertEquals(true, otcBtn.isDisplayed());
        Assert.assertEquals(true, herbBtn.isDisplayed());
    }

    @AfterMethod
    public void tearDown()
    {
        driver.quit();
    }

    @Test(groups = {"functionalTests.FF"})
    public void test_AddMedication_FF()
    {
        addMedication("firefox"); 
    }

    @Test(groups = {"functionalTests.iOS"})
    public void test_AddMedication_iOS()
    {
        addMedication("iOS");
    }
}
Share:
23,721
DarthOpto
Author by

DarthOpto

By Day: I break programs for a living. By Night: I am a holy warrior of the light in World of Warcraft.

Updated on July 05, 2022

Comments

  • DarthOpto
    DarthOpto almost 2 years

    I am running tests with WebDriver, when a test fails, the browser does not close. On a Windows machine this is a huge problem because I then have several instances of the IEDriver still running in the background.

    I have tried a try/catch statement which doesn't seem to work either. If the test fails the browser still remains open. Any help would be greatly appreciated.

    The try catch statement looks something like this:

    try
    {
       Assert.something(something something dark side);
       driver.quit();
    }
    catch(Exception e)
    {
       System.out.println(e)
       driver.quit();
    }
    

    My complete code is below:

    public class ClickAddMedication 
    {
    Browser browser = new Browser();
    
    public void addMedication(String driverName)
    {
        //Open Browser and navigate to page
        WebDriver driver = browser.getDriver(driverName);
        driver.manage().window().maximize();
        driver.get("http://someIP:8080/hmp_patient/index.html");
    
        //Click Add Medication button
        WebElement addBtn = driver.findElement(By.id("add-btn"));
        addBtn.click();
    
        //Verify Add Medication page has loaded successfully
        WebElement rxBtn = driver.findElement(By.className("icon-rx"));
        WebElement otcBtn = driver.findElement(By.className("icon-otc"));
        WebElement herbBtn = driver.findElement(By.className("icon-herb"));
    
        Assert.assertEquals(true, rxBtn.isDisplayed());
        Assert.assertEquals(true, otcBtn.isDisplayed());
        Assert.assertEquals(true, herbBtn.isDisplayed());
    
        driver.quit();
    
    }
    
    @Test(groups = {"functionalTests.FF"})
    public void test_AddMedication_FF()
    {
        addMedication("firefox"); 
    }
    @Test(groups = {"functionalTests.iOS"})
    public void test_AddMedication_iOS()
    {
        addMedication("iOS");
    }
    }
    

    I run the tests with a testng.xml file and would like to have the browser close regardless of whether or not the test passes.

    Below is my Browser class:

    public class Browser 
    {
    public WebDriver getDriver(String driverName)
    {
        WebDriver driver = null;
        if(driverName == "firefox")
        {
            driver = new FirefoxDriver();
        }
        else if(driverName == "chrome")
        {
            File chromeFile = new File ("C:/webdrivers/chromedriver.exe");
            System.setProperty("webdriver.chrome.driver", chromeFile.getAbsolutePath());
            driver = new ChromeDriver();
        }
        else if(driverName == "ie")
        {
            File ieFile = new File("C:/webdrivers/IEDriverServer.exe");
            System.setProperty("webdriver.ie.driver", ieFile.getAbsolutePath());
            driver = new InternetExplorerDriver();
        }
        else if(driverName == "iOS")
        {
            try 
            {
                driver = new RemoteWebDriver(new URL("http://localhost:3001/wd/hub"), DesiredCapabilities.ipad());
            } catch (MalformedURLException e) 
            {
    
                e.printStackTrace();
            }
        }
    
    
        return driver;
    
    }
    }
    
  • DarthOpto
    DarthOpto over 11 years
    Thanks I will give this a shot.
  • DarthOpto
    DarthOpto over 11 years
    I put the following in after my @Test methods and the browser still did not close. This is Java with TestNG. @AfterTest public void closeDriver(String driverName) { WebDriver driver = browser.getDriver(driverName); driver.quit(); }
  • DarthOpto
    DarthOpto over 11 years
    With the above, even if the test passes the driver.quit() is not working.
  • JimEvans
    JimEvans over 11 years
    You'll need to provide more code to get a more precise answer, then. You'll have to show an entire class, with the @Test and @AfterTest methods, as well as give information about what browser.getDriver() does. For instance, if browser.getDriver(driverName); starts a new browser instance, then of course it won't work in your @AfterTest method.
  • DarthOpto
    DarthOpto over 11 years
    Thanks for your help, I have edited my question to have a complete test in it.
  • JimEvans
    JimEvans over 11 years
    This is much more complete, however, you're still missing the contents of Browser.getDriver(). I suspect I know what the problem is, but without seeing that code, I can't be certain. I'll edit my answer here to give a "best guess", but my psychic debugging powers are taking a break today.
  • DarthOpto
    DarthOpto over 11 years
    added the Browser class to my question.
  • JimEvans
    JimEvans over 11 years
    Okay, given what your Browser.getDriver() method is doing (launching a new instance of the browser every time it's called), it's not surprising your attempt to call driver.quit() in the @AfterMethod method is failing. Your closeDriver() method in the first comment of this answer does, in fact, close an instance of the browser, it's just an instance that was created immediately prior by your call to getDriver(). You'll need to refactor your solution somewhat, either by exposing the WebDriver member as I've done, or by altering getDriver() to not create a new browser instance.
  • DarthOpto
    DarthOpto over 11 years
    sorry not understanding your last comment.
  • JimEvans
    JimEvans over 11 years
    Browser.getDriver() launches an instance of the browser every time it's called. Your initial implementation of closeDriver() (found in one of your earlier comments to my answer) calls Browser.getDriver(), which means it's launching a new instance of the browser (not the same one you used in your addMedication() method), and immediately quits it.
  • DarthOpto
    DarthOpto over 11 years
    so I understand that, how do I get it to quit the driver regardless of pass or fail? Currently I just have a driver.quit(); at the end of the test but that does not close the browser, even with a try/catch block it is not closing the browser.
  • JimEvans
    JimEvans over 11 years
    Once again, you want a method marked with the @AfterMethod annotation. Inside that method, you call driver.quit(). It will run regardless of the pass or fail of the test case. The important part is this: your driver variable has to be a member of the test class. You can't access it using your Browser.getDriver() method, not without refactoring your Browser class, anyway. Try the example in my answer, and see if it solves your problem.