I want to run multiple feature files first the partyfeatures.feature and next policyfeature.feature , but I am unable to run the second one . Below is my runner class .
#RunWith(Cucumber.class)
#CucumberOptions(features = {"src/test/resources"},
glue = {"com.cucumber.bhsibase.party.tests"})
public class TestRunner {
//runner class
public static WebDriver driver ;
private TestNGCucumberRunner testNGCucumberRunner;
#BeforeClass(alwaysRun = true)
public void setUpClass() throws Exception {
ConfigReader reader = new ConfigReader();
driver = new FirefoxDriver() ;
driver.get(reader.readurls("ExpressURL"));
testNGCucumberRunner = new TestNGCucumberRunner(this.getClass());
}
#Test(description = "Runs Cucumber Feature", dataProvider = "features")
public void feature(CucumberFeatureWrapper cucumberFeature) {
testNGCucumberRunner.runCucumber(cucumberFeature.getCucumberFeature());
}
#DataProvider
public Object[][] features() {
return testNGCucumberRunner.provideFeatures();
}
#AfterClass(alwaysRun = true)
public void tearDownClass() throws Exception {
driver.quit();
testNGCucumberRunner.finish();
}
}
Related
My issue is mainly to know how to populate TestRail results after Cucumber scenarios are run. I'm trying to have the results from my JUnit tests run set on an existing TestRail run. I have the APIClient and APIException as per this project. I then created this JUnit class also copying that same project. Not sure how to proceed now as first time using Cucumber and JUnit. Our project has also a Hooks class and a MainRunner if that helps?
public class Hooks {
public static WebDriver driver;
#Before
public void initializeTest() {
System.out.println("Testing whether it starts before every scenario");
driver = DriverFactory.startDriver();
}
}
import java.io.File;
#RunWith(Cucumber.class)
#CucumberOptions(
features = {"src/test/java/clinical_noting/feature_files/"},
glue = {"clinical_noting.steps", "clinical_noting.runner"},
monochrome = true,
tags = {"#current"},
plugin = {"pretty", "html:target/cucumber",
"json:target/cucumber.json",
"com.cucumber.listener.ExtentCucumberFormatter:target/cucumber-
reports/report.html"}
)
public class MainRunner {
#AfterClass
public static void writeExtentReport() {
Reporter.loadXMLConfig(new File(FileReaderManager.getInstance().getConfigReader().getReportConfigPath()))
;
}
}
Thanks for the help.
Update
Got TestRail to update when running the JUnit tests separately. Still not sure how to do it after the Cucumber scenario is run though? That's how it's working now:
public class JUnitProject {
private static APIClient client = null;
private static Long runId = 3491l;
private static String caseId = "";
private static int FAIL_STATE = 5;
private static int SUCCESS_STATE = 1;
private static String comment = "";
#Rule
public TestName testName = new TestName();
#BeforeClass
public static void setUp() {
//Login to API
client = testRailApiClient();
}
#Before
public void beforeTest() throws NoSuchMethodException {
Method m = JUnitProject.class.getMethod(testName.getMethodName());
if (m.isAnnotationPresent(TestRails.class)) {
TestRails ta = m.getAnnotation(TestRails.class);
caseId = ta.id();
}
}
#TestRails(id = "430605")
#Test
public void validLogin() {
comment = "another comment";
Assert.assertTrue(true);
}
#Rule
public final TestRule watchman = new TestWatcher() {
Map data = new HashMap();
#Override
public Statement apply(Statement base, Description description) {
return super.apply(base, description);
}
#Override
protected void succeeded(Description description) {
data.put("status_id", SUCCESS_STATE);
}
// This method gets invoked if the test fails for any reason:
#Override
protected void failed(Throwable e, Description description) {
data.put("status_id", FAIL_STATE);
}
// This method gets called when the test finishes, regardless of status
// If the test fails, this will be called after the method above
#Override
protected void finished(Description description) {
try {
data.put("comment", comment);
client.sendPost("add_result_for_case/" + runId + "/" + caseId, data);
} catch (IOException e) {
e.printStackTrace();
} catch (APIException e) {
e.printStackTrace();
}
};
};
}
And the annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD) //on method level
public #interface TestRails {
String id() default "none";
}
Working now. Had to add the scenario param inside the before method and do the TestRail connection from there.
#regressionM1 #TestRails(430605)
Scenario: Verify the user can launch the application
Given I am on the "QA-M1" Clinical Noting application
Then I should be taken to the clinical noting page
And
public class Hooks {
private static APIClient client = null;
private static Long runId = 3491l;
private static String caseId = "";
private static int FAIL_STATE = 5;
private static int SUCCESS_STATE = 1;
private static String SUCCESS_COMMENT = "This test passed with Selenium";
private static String FAILED_COMMENT = "This test failed with Selenium";
#Rule
public TestName testName = new TestName();
public static WebDriver driver;
#Before
public void initializeTest() {
client = testRailApiClient();
System.out.println("Testing whether it starts before every scenario");
driver = DriverFactory.startDriver();
}
#After()
public void tearDown(Scenario scenario) {
String caseIdSplit = "";
for (String s : scenario.getSourceTagNames()) {
if (s.contains("TestRail")) {
caseIdSplit = s.substring(11, 17); // Hardcoded for now as all the ids have 6 characters
System.out.println("Testing whether the browser closes after every scenario" + caseIdSplit);
}
}
caseId = caseIdSplit;
Map data = new HashMap();
if (!scenario.isFailed()) {
data.put("status_id", SUCCESS_STATE);
data.put("comment", SUCCESS_COMMENT);
} else if (scenario.isFailed()) {
data.put("status_id", FAIL_STATE);
data.put("comment", SUCCESS_COMMENT);
}
try {
client.sendPost("add_result_for_case/" + runId + "/" + caseId, data);
} catch (IOException e) {
e.printStackTrace();
} catch (APIException e) {
e.printStackTrace();
}
}
}
Update
Wrote a post on this here
ReporterClass.Java:
package POM_Classes;
import com.aventstack.extentreports.AnalysisStrategy;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.reporter.ExtentHtmlReporter;
public class ReporterClass {
public static ExtentHtmlReporter html;
public ExtentReports extent;
public ExtentTest test, suiteTest;
public String testCaseName, testNodes, testDescription, category, authors;
public void startResult() {
html = new ExtentHtmlReporter("./reports/result.html");
html.setAppendExisting(true);
extent = new ExtentReports();
extent.attachReporter(html);
}
/*public ExtentTest startTestModule(String testCaseName, String testDescription) {
suiteTest = extent.createTest(testCaseName, testDescription);
return suiteTest;
}*/
public ExtentTest startTestCase(String testName) {
System.out.println(testName);
test = extent.createTest(testName);
return test;
}
public void reportStep(String desc, String status) {
if (status.equalsIgnoreCase("PASS")) {
test.pass(desc);
} else if (status.equalsIgnoreCase("FAIL")) {
test.fail(desc);
} else if (status.equalsIgnoreCase("WARNING")) {
test.warning(desc);
} else if (status.equalsIgnoreCase("INFO")) {
test.info(desc);
}
}
public void endTestcase() {
extent.setAnalysisStrategy(AnalysisStrategy.CLASS);
}
public void endResult() {
extent.flush();
}
}
Usage:
#Test
public void 961_NavigateToMyAlertsAndAddNewAlerts()
throws IOException, InterruptedException, ATUTestRecorderException, APIException {
driver = launchTargetUrl(this.getClass().getSimpleName().toString());
startResult();
test = startTestCase(Thread.currentThread().getStackTrace()[1].getMethodName().toString());
LoginApplication(driver,transactionusername, transactionuserpassword,test);
HomePage homePage = new HomePage(driver,test);
homePage.MyAlerts.click();
MyAlerts myalerts = new MyAlerts(driver,test);
String selectedcardName;
selectedcardName = driver.findElement(myalerts.cardName).getText().trim();
System.out.println(selectedcardName);
}
#AfterMethod
public void afterMethod(ITestResult result) throws ATUTestRecorderException {
resultOfTest(result);
endTestcase();
endResult();
closeBrowsers(driver);
}
The test case which first gets completed has the report and if the another test case is completed then that result overrides the old one..
If I change public static ExtentReports extent; then it maintains only thread so it logs only one test case and the other parallel execution is not even recorded.. How to resolve this?
Ok, here you go. I haven't tested this yet, but this should allow you to use Extent with parallel usage.
Reporter:
public abstract class ReporterClass {
private static final ExtentReports EXTENT = ExtentManager.getInstance();
public ExtentTest test, suiteTest;
public String testCaseName, testNodes, testDescription, category, authors;
public synchronized ExtentTest startTestCase(String testName) {
System.out.println(testName);
return ExtentTestManager.createTest(testName);
}
public synchronized void reportStep(String desc, String status) {
if (status.equalsIgnoreCase("PASS")) {
ExtentTestManager.getTest().pass(desc);
} else if (status.equalsIgnoreCase("FAIL")) {
ExtentTestManager.getTest().fail(desc);
} else if (status.equalsIgnoreCase("WARNING")) {
ExtentTestManager.getTest().warning(desc);
} else if (status.equalsIgnoreCase("INFO")) {
ExtentTestManager.getTest().info(desc);
}
}
public synchronized void endResult() {
EXTENT.flush();
}
#BeforeMethod
public synchronized void beforeMethod(Method method) {
startTestCase(method.getName());
}
#AfterMethod
public synchronized void afterMethod(ITestResult result) throws ATUTestRecorderException {
reportStep(result.getThrowable(), result.getStatus());
endResult();
closeBrowsers(driver);
}
}
Base:
public abstract class BaseClass extends ReporterClass {
// .. abstractions
}
Extent utils:
public class ExtentTestManager {
static Map<Integer, ExtentTest> extentTestMap = new HashMap<Integer, ExtentTest>();
private static final ExtentReports EXTENT = ExtentManager.getInstance();
public static synchronized ExtentTest getTest() {
return extentTestMap.get((int) (long) (Thread.currentThread().getId()));
}
public static synchronized ExtentTest createTest(String testName) {
return createTest(testName, "");
}
public static synchronized ExtentTest createTest(String testName, String desc) {
ExtentTest test = EXTENT.createTest(testName, desc);
extentTestMap.put((int) (long) (Thread.currentThread().getId()), test);
return test;
}
}
public class ExtentManager {
private static ExtentReports extent;
public synchronized static ExtentReports getInstance() {
if (extent == null) {
createInstance("reports/extent.html");
}
return extent;
}
public synchronized static ExtentReports createInstance(String fileName) {
ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(fileName);
htmlReporter.config().setTestViewChartLocation(ChartLocation.BOTTOM);
htmlReporter.config().setChartVisibilityOnOpen(true);
htmlReporter.config().setTheme(Theme.STANDARD);
htmlReporter.config().setDocumentTitle(fileName);
htmlReporter.config().setEncoding("utf-8");
htmlReporter.config().setReportName(fileName);
htmlReporter.setAppendExisting(true);
extent = new ExtentReports();
extent.setAnalysisStrategy(AnalysisStrategy.CLASS);
extent.attachReporter(htmlReporter);
return extent;
}
}
Finally, your slim tests. Notice there is 0 lines of reporter code here - see ReporterClass.
public class MyTestsClass extends BaseClass {
#Test
public void 961_NavigateToMyAlertsAndAddNewAlerts()
throws IOException, InterruptedException, ATUTestRecorderException, APIException {
driver = launchTargetUrl(this.getClass().getSimpleName().toString());
LoginApplication(driver,transactionusername, transactionuserpassword,test);
HomePage homePage = new HomePage(driver,test);
homePage.MyAlerts.click();
MyAlerts myalerts = new MyAlerts(driver,test);
String selectedcardName;
selectedcardName = driver.findElement(myalerts.cardName).getText().trim();
System.out.println(selectedcardName);
}
}
//Add below class in your Project. First you need to add the respective object and
//call them respectively. Declaring Extent and Driver as static is a big problem in
//Parallel/execution.
//Avoid using static as far as possible by using the below class.
import java.util.ArrayList;
import java.util.List;
import org.openqa.selenium.WebDriver;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
public class WebDriverFactory {
private static ThreadLocal<WebDriver> drivers=new ThreadLocal<>();
private static List<WebDriver> storeDrivers=new ArrayList<WebDriver>();
private static List<ExtentTest> extent=new ArrayList<ExtentTest>();
private static ThreadLocal<ExtentTest> reports=new ThreadLocal<ExtentTest>();
static
{
Runtime.getRuntime().addShutdownHook(new Thread(){
public void run()
{
storeDrivers.stream().forEach(WebDriver::quit);
}
});
}
public static WebDriver getDriver()
{
return drivers.get();
}
public static ExtentTest getextentReportObject()
{
return reports.get();
}
public static void addDriver(WebDriver driver)
{
storeDrivers.add(driver);
drivers.set(driver);
}
public static void addExtentReportObject(ExtentTest report)
{
extent.add(report);
reports.set(report);
}
public static void removeDriver()
{
storeDrivers.remove(drivers.get());
drivers.remove();
}
}
//Add and Invoke the object in the following way
/*** Add and invoke the object in the below fashion **/
WebDriverFactory.addExtentReportObject(extent.createTest("Monitor Scenario
").createNode("Monitor Page Validation"));
WebDriverFactory.getextentReportObject().assignCategory("#SmokeTest");
I have two TestNG classes with one test method in each. Each test class has its own #Dataprovider. Each test executes functionality on a web application using Selenium Webdriver. The driver is created for each TestNG class via a factory method and threadlocal so driver should be threadsafe. However when running the tests in parallel using testng.xml the same data is being used across both tests causing one to fail. Here is the code. I'm thinking it might be a problem with the thread safety of the Excel Utility class.
/ DriverFactory
#Listeners(ScreenshotListener.class)
public class DriverFactory {
public final static String URL = "http://localhost/Quotation/Development/index.php";
private static List<WebDriverThread> webDriverThreadPool = Collections.synchronizedList(new ArrayList<WebDriverThread>());
private static ThreadLocal<WebDriverThread> driverThread;
#BeforeClass
public static void instantiateDriverObject() {
System.out.println("Before Class");
driverThread = new ThreadLocal<WebDriverThread>() {
#Override
protected WebDriverThread initialValue() {
WebDriverThread webDriverThread = new WebDriverThread();
webDriverThreadPool.add(webDriverThread);
return webDriverThread;}};
}
#BeforeTest
public void setUp() throws Exception {
System.out.println("Before Test");}
public static WebDriver getDriver() throws Exception {
return driverThread.get().getDriver();}
protected String debug(String methodName) throws Exception {
return methodName + " running on Thread " + Thread.currentThread().getId() +
" with instance as " + this + " and driver " + driverThread.get().getDriver().toString();
}
#AfterSuite
public static void closeDriverObjects() {
System.out.println(webDriverThreadPool.size());
for (WebDriverThread webDriverThread : webDriverThreadPool) {
webDriverThread.quitDriver();}
}
}
// WebDriver thread
public class WebDriverThread {
private WebDriver webdriver;
private DriverType selectedDriverType;
private final DriverType defaultDriverType = FIREFOX;
private final String browser = "CHROME"; //System.getProperty("browser").toUpperCase();
private final String operatingSystem = System.getProperty("os.name").toUpperCase();
private final String systemArchitecture = System.getProperty("os.arch");
private final boolean useRemoteWebDriver = Boolean.getBoolean("remoteDriver");
public WebDriver getDriver() throws Exception {
if (null == webdriver) {
selectedDriverType = determineEffectiveDriverType();
DesiredCapabilities desiredCapabilities = selectedDriverType.getDesiredCapabilities();
instantiateWebDriver(desiredCapabilities);}
return webdriver;}
public void quitDriver() {
if (null != webdriver) {
webdriver.quit();
webdriver = null;
}}
private DriverType determineEffectiveDriverType() {
DriverType driverType = defaultDriverType;
try {
driverType = valueOf(browser);}
catch (IllegalArgumentException ignored) {
System.err.println("Unknown driver specified,defaulting to '" + driverType + "'...");}
catch (NullPointerException ignored) {
System.err.println("No driver specified, defaulting to '" + driverType + "'...");}
return driverType;}
private void instantiateWebDriver(DesiredCapabilities desiredCapabilities) throws MalformedURLException {
System.out.println(" ");
System.out.println("Current Operating System: " + operatingSystem);
System.out.println("Current Architecture: " + systemArchitecture);
System.out.println("Current Browser Selection: " + selectedDriverType);
System.out.println(" ");
if (useRemoteWebDriver) {
URL seleniumGridURL = new URL(System.getProperty("gridURL"));
webdriver = new RemoteWebDriver(seleniumGridURL,desiredCapabilities);
}
else
webdriver = selectedDriverType.getWebDriverObject(desiredCapabilities);
}
}
// ValidLoginTest
public class ValidLoginTest extends DriverFactory{
#BeforeMethod
public void setup() throws Exception {
System.err.println(debug("validLoginTest"));
}
//#Test(dataProvider="ValidLogin" ,dependsOnMethods = { "inValidLoginTest" })
#Test(dataProvider="ValidLogin")
public void validLoginTest(String username, String password, String expectedUserName, String expectedUserEmail) throws Exception {
Login login = new Login();
getDriver().get(URL);
String[] loggedin = login.navigateTo()
.enterUserName(username)
.enterPassword(password)
.andSubmit()
.andCheckLoggedIn();
assertEquals(loggedin[0],expectedUserName);
assertEquals(loggedin[1],expectedUserEmail);
}
#AfterMethod
public void teardown() throws Exception {
JavascriptExecutor jsExecutor = (JavascriptExecutor) getDriver();
jsExecutor.executeScript("sessionStorage.clear();");
}
#DataProvider
public Object[][] ValidLogin() throws Exception{
Object[][] testObjArray = ExcelUtils.getTableArray("SystemTestData.xlsx","ValidLogin");
return (testObjArray);}
}
public class InvalidLoginTest extends DriverFactory{
#BeforeMethod
public void setup() throws Exception {
System.err.println(debug("inValidLoginTest"));
}
#Test(dataProvider="InvalidLogin")
public void inValidLoginTest(String username, String password, String expectedResult) throws Exception {
Login login = new Login();
getDriver().get(URL);
String error = login.navigateTo()
.enterUserName(username)
.enterPassword(password)
.andSubmit()
.andCheckValidation();
assertEquals(error, expectedResult);
login.andClose();
}
#DataProvider
public Object[][] InvalidLogin() throws Exception{
Object[][] testObjArray = ExcelUtils.getTableArray("SystemTestData.xlsx","InvalidLogin");
return (testObjArray);}
}
public class Login {
#FindBy(xpath = "/html/body/nav/div/div[2]/ul/li[3]/a")
private WebElement loginMenu;
#FindBy(name = "user")
private WebElement usernameLocator;
#FindBy(name = "password")
private WebElement passwordLocator;
#FindBy(id = "loginUser")
private WebElement loginUserLocator;
#FindBy(css = "#loginForm > div:nth-child(2) > button:nth-child(2)")
private WebElement closeLocator;
#FindBy(id = "loginError")
private WebElement error;
#FindBy(xpath = "/html/body/nav/div/div[2]/ul/li[3]/ul/li[1]/div/div/div/p[1]/strong")
private WebElement loggedInUserName;
#FindBy(xpath = "/html/body/nav/div/div[2]/ul/li[3]/ul/li[1]/div/div/div/p[2]/strong")
private WebElement loggedInUserEmail;
#FindBy(xpath = "/html/body/nav/div/div[2]/ul/li[3]")
private WebElement account;
private WebDriverWait wait;
public Login() throws Exception {
PageFactory.initElements(DriverFactory.getDriver(), this);
wait = new WebDriverWait(DriverFactory.getDriver(), 30);
System.out.println("Login " + DriverFactory.getDriver().toString());
}
public Login navigateTo() throws Exception {
wait.until(ExpectedConditions.visibilityOf(loginMenu));
loginMenu.click();
return this;
}
public Login enterUserName(String username) {
wait.until(ExpectedConditions.visibilityOf(usernameLocator));
usernameLocator.clear();
for(int i = 0; i < username.length(); i++){
char c = username.charAt(i);
String s = new StringBuilder().append(c).toString();
usernameLocator.sendKeys(s);
}
return this;
}
public Login enterPassword(String password) {
wait.until(ExpectedConditions.visibilityOf(passwordLocator));
passwordLocator.clear();
passwordLocator.sendKeys(password);
return this;
}
public Login andSubmit() {
wait.until(ExpectedConditions.visibilityOf(loginUserLocator));
loginUserLocator.click();
return this;
}
public String[] andCheckLoggedIn() {
String[] actualResult = new String[2];
wait.until(ExpectedConditions.visibilityOf(account));
account.click();
wait.until(ExpectedConditions.visibilityOf(loggedInUserName));
actualResult[0] = loggedInUserName.getText();
actualResult[1] = loggedInUserEmail.getText();
return actualResult;
}
public String andCheckValidation() {
wait.until(ExpectedConditions.visibilityOfAllElements(error));
return error.getText();
}
public void andClose() throws Exception {
wait.until(ExpectedConditions.visibilityOf(closeLocator));
closeLocator.click();
}
}
public class ExcelUtils {
private static XSSFSheet ExcelWSheet;
private static XSSFWorkbook ExcelWBook;
private static XSSFCell Cell;
private static XSSFRow Row;
public static Object[][] getTableArray(String FilePath, String SheetName) throws Exception {
String[][] tabArray = null;
try {
FileInputStream ExcelFile = new FileInputStream(FilePath);
// Access the required test data sheet
ExcelWBook = new XSSFWorkbook(ExcelFile);
ExcelWSheet = ExcelWBook.getSheet(SheetName);
int startRow = 1;
int startCol = 1;
int totalRows = ExcelWSheet.getLastRowNum();
int totalCols = ExcelWSheet.getRow(0).getLastCellNum();
tabArray = new String[totalRows][totalCols -startCol];
for (int row = startRow; row <= totalRows; row++) {
for (int col = startCol; col < totalCols; col++){
tabArray[row - startRow][col - startCol] = getCellData(row, col);
}}}
catch (FileNotFoundException e){
System.out.println("Could not read the Excel sheet");
e.printStackTrace();
}
catch (IOException e){
System.out.println("Could not read the Excel sheet");
e.printStackTrace();
}
return(tabArray);
}
public static String getCellData(int RowNum, int ColNum) throws Exception {
try{
Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
if (Cell == null || Cell.getCellTypeEnum() == CellType.BLANK) {
return "";
}else{
String CellData = Cell.getStringCellValue();
return CellData;
}}catch (Exception e){
System.out.println(e.getMessage());
throw (e);
}}}
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Quotation" parallel="classes" thread-count="3" verbose="1" >
<test name="System Test" >
<classes>
<class name="com.quotation.systemtest.tests.ValidLoginTest"/>
<class name="com.quotation.systemtest.tests.InvalidLoginTest"/>
</classes>
</test>
</suite>
[Testng_Result][1]
[1]: https://i.stack.imgur.com/vLx0y.png
Currently, I am using Selenium TestNG and Extent Reports framework for reporting. I am facing a problem where all are my test cases are showing Pass and not showing Fail.
#BeforeTest
public void setUp()
{
//where we need to generate the report
htmlReporter = new ExtentHtmlReporter(System.getProperty("user.dir")+"/test-output/MyReport.html");
extent = new ExtentReports();
extent.attachReporter(htmlReporter);
// Set our document title, theme etc..
htmlReporter.config().setDocumentTitle("My Test Report");
htmlReporter.config().setReportName("Test Report");
htmlReporter.config().setTestViewChartLocation(ChartLocation.TOP);
htmlReporter.config().setTheme(Theme.DARK);
}
#Test
public void On_Page_IM() throws InterruptedException {
test = extent.createTest("On_Page_IM");
wd.manage().window().maximize();
Thread.sleep(10000);
test.log(Status.INFO,"On page intent media: Show");
}
#AfterSuite
public void tearDown()
{
extent.flush();
wd.quit();
}
After Added this code its solved
#AfterMethod
public void getResult(ITestResult result)
{
if(result.getStatus()==ITestResult.FAILURE)
{
test.log(Status.FAIL, result.getThrowable());
}
// extent.endTest(test);
}
Just add below code at end of ur tests
#AfterMethod
public void AfterMethod(ITestResult result) {
if (result.getStatus() == ITestResult.FAILURE) {
test.log(Status.FAIL,
MarkupHelper.createLabel(result.getName()
+ " Test case FAILED due to below issues:",
ExtentColor.RED));
test.fail(result.getThrowable());
} else if (result.getStatus() == ITestResult.SUCCESS) {
test.log(
Status.PASS,
MarkupHelper.createLabel(result.getName()
+ " Test Case PASSED", ExtentColor.GREEN));
} else {
test.log(
Status.SKIP,
MarkupHelper.createLabel(result.getName()
+ " Test Case SKIPPED", ExtentColor.ORANGE));
test.skip(result.getThrowable());
}
}
#AfterTest
public void AfterTest() {
extent.flush();
}
Selenium WebDriver 4 + JUnit 5 + Extent Reports 5 (JDK 17)
I used this and this to write the modern JUnit 5 solution, since most examples are for the older TestNG. ExtentHtmlReporter has also been deprecated.
abstract class BaseTest {
private static ExtentReports extent; // Prevent overwriting reports per test
protected WebDriver driver; // WebDriver should never be static
#RegisterExtension
protected AfterEachExtension afterEachExtension = new AfterEachExtension();
#BeforeAll
public static void beforeAll() {
extent = new ExtentReports();
spark = new ExtentSparkReporter("target/spark-reports/index.html");
extent.attachReporter(spark);
spark.config(
ExtentSparkReporterConfig.builder()
.theme(Theme.DARK)
.documentTitle("Extent Reports")
.build()
);
}
#BeforeEach
public void beforeEach() {
driver = // Initialise driver
}
#AfterEach
public void afterEach() {
AfterEachExtension.setExtent(extent);
afterEachExtension.setDriver(driver);
}
#AfterAll
public static void afterAll() {
extent.flush();
}
}
import com.aventstack.extentreports.Status;
// Other imports
public class AfterEachExtension implements AfterEachCallback {
private static ExtentReports extent;
private WebDriver driver;
public static void setExtent(ExtentReports extent) {
AfterEachExtension.extent = extent;
}
public void setDriver(WebDriver driver) {
this.driver = driver;
}
#Override
public void afterEach(ExtensionContext context) throws Exception {
var test = extent.createTest(context.getDisplayName());
context.getExecutionException().ifPresent(value -> test.log(Status.FAIL, value));
driver.quit();
}
}
I am having some difficulty tweaking ExtentReports to provide the desired output.
I have a simple test framework with TestNG, using a TestBase class to do the heavy lifting to keep tests simple. I wish to implement ExtentReports in a simple fashion, using the TestNG ITestResult interface to report Pass, Fail and Unknown.
Here are example tests, 1 pass and 1 deliberate fail:
public class BBCTest extends TestBase{
#Test
public void bbcHomepagePass() throws MalformedURLException {
assertThat(driver.getTitle(), (equalTo("BBC - Home")));
}
#Test
public void bbcHomePageFail() throws MalformedURLException {
assertThat(driver.getTitle(), (equalTo("BBC - Fail")));
}
And here is the relevant section in TestBase:
public class TestBase implements Config {
protected WebDriver driver = null;
private Logger APPLICATION_LOGS = LoggerFactory.getLogger(getClass());
private static ExtentReports extent;
private static ExtentTest test;
private static ITestContext context;
private static String webSessionId;
#BeforeSuite
#Parameters({"env", "browser"})
public void beforeSuite(String env, String browser) {
String f = System.getProperty("user.dir") + "\\test-output\\FabrixExtentReport.html";
ExtentHtmlReporter h = new ExtentHtmlReporter(f);
extent = new ExtentReports();
extent.attachReporter(h);
extent.setSystemInfo("browser: ", browser);
extent.setSystemInfo("env: ", env);
}
#BeforeClass
#Parameters({"env", "browser", "login", "mode"})
public void initialiseTests(String env, String browser, String login, String mode) throws MalformedURLException {
EnvironmentConfiguration.populate(env);
WebDriverConfigBean webDriverConfig = aWebDriverConfig()
.withBrowser(browser)
.withDeploymentEnvironment(env)
.withSeleniumMode(mode);
driver = WebDriverManager.openBrowser(webDriverConfig, getClass());
String baseURL = EnvironmentConfiguration.getBaseURL();
String loginURL = EnvironmentConfiguration.getLoginURL();
APPLICATION_LOGS.debug("Will use baseURL " + baseURL);
switch (login) {
case "true":
visit(baseURL + loginURL);
break;
default:
visit(baseURL);
break;
}
driver.manage().deleteAllCookies();
}
#BeforeMethod
public final void beforeTests(Method method) throws InterruptedException {
test = extent.createTest(method.getName());
try {
waitForPageToLoad();
webSessionId = getWebSessionId();
} catch (NullPointerException e) {
APPLICATION_LOGS.error("could not get SessionID");
}
}
#AfterMethod
public void runAfterTest(ITestResult result) throws IOException {
switch (result.getStatus()) {
case ITestResult.FAILURE:
test.fail(result.getThrowable());
test.fail("Screenshot below: " + test.addScreenCaptureFromPath(takeScreenShot(result.getMethod().getMethodName())));
test.fail("WebSessionId: " + webSessionId);
break;
case ITestResult.SKIP:
test.skip(result.getThrowable());
break;
case ITestResult.SUCCESS:
test.pass("Passed");
break;
default:
break;
}
}
private String takeScreenShot(String methodName) {
String path = System.getProperty("user.dir") + "\\test-output\\" + methodName + ".jpg";
try {
File screenshotFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screenshotFile, new File(path));
} catch (Exception e) {
APPLICATION_LOGS.error("Could not write screenshot" + e);
}
return path;
}
#AfterClass
public void tearDown() {
driver.quit();
}
#AfterSuite()
public void afterSuite() {
extent.flush();
}
Here is the report:
The issues are:
The name of the failed test is not recorded at left hand menu
The screenshot is not displayed despite correctly being taken
It is reporting both a Pass and Unexpected for the passed test
Version 3.0
Most of code is provided by person created this library, i just modified to your needs.
public class TestBase {
private static ExtentReports extent;
private static ExtentTest test;
#BeforeSuite
public void runBeforeEverything() {
String f = System.getProperty("user.dir")+ "/test-output/MyExtentReport.html";
ExtentHtmlReporter h = new ExtentHtmlReporter(f);
extent = new ExtentReports();
extent.attachReporter(h);
}
#BeforeMethod
public void runBeforeTest(Method method) {
test = extent.createTest(method.getName());
}
#AfterMethod
public void runAfterTest(ITestResult result) {
switch (result.getStatus()) {
case ITestResult.FAILURE:
test.fail(result.getThrowable());
test.fail("Screenshot below: " + test.addScreenCaptureFromPath(takeScreenShot(result.getMethod().getMethodName())));
break;
case ITestResult.SKIP:
test.skip(result.getThrowable());
break;
case ITestResult.SUCCESS:
test.pass("Passed");
break;
default:
break;
}
extent.flush();
}
protected String takeScreenShot(String methodName) {
String path = "./screenshots/" + methodName + ".png";
try {
File screenshotFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screenshotFile, new File(path));
} catch (Exception e) {
APPLICATION_LOGS.error("Could not write screenshot" + e);
}
return path;
}
}
You need several changes to make. Instantiate the ExtentReport & add configuration information in any of the configuration methods except BeforeClass.
#BeforeTest
#Parameters({"env", "browser"})
public void initialiseTests(String env, String browser, String emulatorMode, String mode) {
EnvironmentConfiguration.populate(env);
WebDriverConfigBean webDriverConfig = aWebDriverConfig()
.withBrowser(browser)
.withDeploymentEnvironment(env)
.withSeleniumMode(mode);
driver = WebDriverManager.openBrowser(webDriverConfig, getClass());
APPLICATION_LOGS.debug("Will use baseURL " + EnvironmentConfiguration.getBaseURL());
try {
visit(EnvironmentConfiguration.getBaseURL());
} catch (MalformedURLException e) {
e.printStackTrace();
}
driver.manage().deleteAllCookies();
}
Initailize test = extent.startTest(testName); in the #BeforeMethod section.
#BeforeMethod
public void beforeM(Method m) {
test = extent.startTest(m.getName());
}
And, you may call extent.endTest(test); in the #AfterTest method.
#AfterTest
public void afterTests() {
extent.endTest(test);
extent.close();
}
}
And, to log your step info call test.log(LogStatus, "your info to show"); with appropirate status.