Reputation: 2499
I need to:
The tests will be started via TeamCity. I create a TestWatcher object to listen for test results, and this TestWatcher is included in each JUnit class that contains tests. I had a listener which would listen to when the entire suite is completed, but I had to add that programmatically. Since I am now using TeamCity to run the tests and generate results, I believe I have lost that capability. I have been asked to also produce a PDF report with the TeamCity results. All I need to know is when the tests are finished so I can know when to start building my report. Is there anyway to accomplish this by just using a TestWatcher?
Below is what my TestWatcher looks like at the moment. BaseTestResult is just a class that contains results of the tests, and organizes them in order to print them out easier. I am also using Selenium, and the driver variable is of type WebDriver:
@Rule
public TestWatcher watchman = new TestWatcher() {
private BaseTestResult currentTest;
private long startTime;
private long endTime;
@Override
protected void starting(Description d) {
startTime = System.currentTimeMillis();
currentTest = new BaseTestResult(d);
currentTest.setBrowser(type);
if (d.getAnnotation(TestDescription.class) != null) {
currentTest.setDescription(d.getAnnotation(
TestDescription.class).description());
}
currentTest.setSuite(d.getTestClass().getName());
}
@Override
protected void succeeded(Description d) {
currentTest.setSucceeded(true);
}
@Override
protected void failed(Throwable e, Description d) {
currentTest.setThrowable(e);
}
@Override
protected void finished(Description d) {
endTime = System.currentTimeMillis();
currentTest.setRuntime(endTime - startTime);
String fileName = d.getMethodName() + type + ".png";
File srcFile = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.FILE);
String filePath = "./screens/" + fileName;
try {
FileUtils.copyFile(srcFile, new File(filePath));
currentTest.setScreenshotPath(filePath);
} catch (IOException e) {
log.severe(e.toString());
}
if (currentTest.getSucceeded()) {
BaseListener.getSuiteResult().addPassed(currentTest);
} else {
BaseListener.getSuiteResult().addFailed(currentTest);
}
// Quit, the web driver
if (driver != null) {
driver.quit();
}
}
};
Upvotes: 4
Views: 15657
Reputation: 127
This worked for me
@ClassRule
public Static TestWatcher watchman= new TestWatcher() {
@Override
protected void failed(Throwable e, Description description) {
logger.info(description.getMethodName()+"Failed!"+" "+e.getMessage());
}
@Override
protected void succeeded(Description description) {
logger.info(description.getMethodName()+" " + "success!");
}
@Override
protected void finished(Description desc) {
logger.info("Suite completed!");
}
};
Upvotes: 1
Reputation: 38444
You can do this:
@ClassRule // the magic is done here
public static TestRule classWatchman = new TestWatcher() {
@Override
protected void starting(Description desc) {
System.out.println(desc.testCount()); // insert actual logic here
}
};
This watches whole class instead of every test. That means that it gives you the number of tests in a suite on the start of the suite. Then, every time you call BaseListener.getSuiteResult().addPassed(currentTest);
or BaseListener.getSuiteResult().addFailed(currentTest);
you can check whether you have already added the number of tests in a suite (meaning the suite is done).
Or, even better,
@ClassRule
public static TestRule classWatchman = new TestWatcher() {
@Override
protected void finished(Description desc) {
System.out.println("Suite completed!"); // insert actual logic here
}
};
If you have multiple classes containing tests, you can create a single AllMyTests class containing all of those! This AllMyTests class can be then run by JUnit. In this case, @ClassRule will behave as a @SuiteRule (which doesn't exist).
@RunWith(Suite.class)
@Suite.SuiteClasses({ First.class, Second.class, Third.class })
public class AllMyTests {
// nothing to do
}
Upvotes: 7