junit TestWatcher failed and finished methods firing time

那年仲夏 提交于 2019-12-11 10:38:55

问题


I am writing some functional tests with webdriver and executing them with JUnit. I am trying to make use of TestWatcher class so everytime an event occurs a specific action could be done. I am overriding the finished and failed methods, but it seems to be that these are fired virtually simultaneously, so the driver has been already disposed by finish method before the failed method could do it's stuff.

The TestWatcher is following:

public class TestRules extends TestWatcher {

private static WebDriver driver;
private static final Logger Log = LogManager.getLogger(TestRules.class);

public TestRules() {
    if (driver == null)
        try {
            driver = TestHelpers.getWebDriver();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
}

@Override
protected void starting(Description description){
    Log.info(String.format("Started test: %s::%s", description.getClassName(), description.getMethodName()));
    try {
        new LoginTest().testDoLogin();
    } catch (Exception e) {
        Log.error(e);
    }
}

@Override
protected void failed(Throwable e, Description description) {
    File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);

    String path = String.format("C:\\localdev\\screenshot\\%d__%s_%s.png",
            Calendar.getInstance().getTimeInMillis(), description.getClassName(), description.getMethodName());
    try {
        FileUtils.copyFile(scrFile, new File(path));
    } catch (IOException ioe) {
        Log.error(ioe);
    }
    Log.error(String.format("Error: %s\nScreenshot: %s", e.getMessage(), path));
}

@Override
protected void finished(Description description) {
    Log.info(String.format("Finished test: %s::%s", description.getClassName(), description.getMethodName()));
    try {
        // This actually calling driver.quit() <- (driver == WebDriver)
        TestHelpers.close();
    } catch (Exception e) {
        Log.error(e);
    }
}

}

The test could be something like this:

public class testSomething {
private static final Logger Log = LogManager.getLogger(testSomething.class);

@Rule
public TestRules testRules = new TestRules();

@Test
public void filterTableByNameWildcard() throws Exception {
    Log.info("Starting the test filterTable");

    MainView mainView = getMainView();
    String searchString = "A*";
    mainView.setFilterParametersAndDoFilter(searchString, "", true, true);
    mainView.validateWildCardSearchReturnsCorrectData(searchString);
    // Random failing point for testing
    Assert.assertTrue(false);

When i run my test, i am getting a following error:

java.lang.AssertionError: 
Expected :true
Actual   :false
 <Click to see difference>
    at org.junit.Assert.fail(Assert.java:88)
    at org.junit.Assert.failNotEquals(Assert.java:789)
    at org.junit.Assert.assertEquals(Assert.java:118)
    at org.junit.Assert.assertEquals(Assert.java:144)
    at xxx.Tests.xxx.testSomething.filterSomething(TestSomething.java:34)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
.... skipped


org.openqa.selenium.remote.SessionNotFoundException: The FirefoxDriver cannot be used after quit() was called.
Build info: version: '2.33.0', revision: '4e90c97', time: '2013-05-22 15:33:32'
System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.7.0_21'
Driver info: driver.version: FirefoxDriver
    at org.openqa.selenium.firefox.FirefoxDriver$LazyCommandExecutor.execute(FirefoxDriver.java:352)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:527)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:569)
    at org.openqa.selenium.firefox.FirefoxDriver.getScreenshotAs(FirefoxDriver.java:316)
    at xxx.TestHelpers.TestRules.failed(TestRules.java:47)
    at org.junit.rules.TestWatcher.failedQuietly(TestWatcher.java:84)
    at org.junit.rules.TestWatcher.access$300(TestWatcher.java:46)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:62)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)

Any ideas how to get pass it?

EDIT: From documentation:

protected void finished(Description description) Invoked when a test method finishes (whether passing or failing)

protected void failed(Throwable e, Description description) Invoked when a test fails

It would make sense, that firstly the "failed" is called and after that, the "finished" is called, but it seems to be the other way around.


回答1:


Your problem is a shared resource that isn't created fresh at every execution. I created a small example that will show this. Take a look at my comment to your comment.



来源:https://stackoverflow.com/questions/18510854/junit-testwatcher-failed-and-finished-methods-firing-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!