I have written the following test using the testNG annotations:
public class Create {
WebDriver driver;
#BeforeClass
public void testsetup() {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().window().maximize();
}
#BeforeMethod
public void Login() {
driver.get("www.xyz.com");//just an example
}
#Test(priority=3)
public void AccountCreate() {
System.out.println("Test3");
}
}
#Test(priority=1)
public void CompanyCreate() {
System.out.println("Test1");
}
#Test(priority=2)
public void VerifyResult() {
System.out.println("Test2");
}
}
#AfterMethod
public void Logout() {
System.out.println("print after method");
}
#AfterClass
public void CloseBrowser() {
driver.close();
}
}
The o/p is like this:
print after method
test1
print after method
test2
print after method
test3
Observations; #BeforeClass executes first, then #Beforemethod executes, then #Aftermethod and then #Test(priority=1), #Aftermethod then #Beforemethod and then #Test(priority=2) and so on.
But after all the #Test run, then only the #Aftermethod executes. Anyone, please help me on this. I really couldn't find what exactly is the problem.
There is no issue in your code block. I took your code, simplified it a bit replacing the Browsing Context line with Sysout() statements and here is the execution result:
Code Block:
public class Aftermethod_Test {
WebDriver driver;
#BeforeClass
public void testsetup() {
System.out.println("print before class");
}
#BeforeMethod
public void Login() {
System.out.println("print before method");
}
#Test(priority=3)
public void AccountCreate() {
System.out.println("Test3");
}
#Test(priority=1)
public void CompanyCreate() {
System.out.println("Test1");
}
#Test(priority=2)
public void VerifyResult() {
System.out.println("Test2");
}
#AfterMethod
public void Logout() {
System.out.println("print after method");
}
#AfterClass
public void CloseBrowser() {
System.out.println("print after class");
}
}
Console Output:
print before class
print before method
Test1
print after method
print before method
Test2
print after method
print before method
Test3
print after method
print after class
PASSED: CompanyCreate
PASSED: VerifyResult
PASSED: AccountCreate
===============================================
Default test
Tests run: 3, Failures: 0, Skips: 0
===============================================
===============================================
Default suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================
Analysis
This observation looks just perfect and as per your expectation.
Your usecase
Earlier it was observed at times Sysout() from #Test reaches to the console later then #Aftermethod. A simple solution would be to update your test environment with all the latest binaries:
TestNG: <version>6.10</version>
JDK is upgraded to current levels JDK 8u251.
Selenium is upgraded to current levels Version 3.141.59.
Reference
You can find a detailed relevant discussion in:
TestNG - Order of Tests execution in selenium script
How to demonstrate a real time example of using BeforeTest, AfterTest, BeforeSuite, AfterSuite, BeforeClass, AfterClass annotations in TestNG
Related
I'm running my selenium code for Page object model using testNG, #BeforeTest will run only once for every test and #BeforeMethod will run everytime for every test. So which annotation would be preferable to use for page object model ?
#BeforeMethod
public void setUp() throws IOException
{
initialisation();
loginPage = new Login();
loginPage.login(prop.getProperty("username"), prop.getProperty("password"));
ot = new OpenTasks();
active = new ActiveProjects();
}
#Test(priority=1)
public void validateTitle() throws IOException, InterruptedException
{
String custTitle = ot.verifyTitle();
Assert.assertEquals(custTitle, "actiTIME - Open Tasks", "Title not matched");
}
#Test(priority=2)
public void verifyProjectLink() throws IOException, InterruptedException
{
active = ot.clickOnProjectLink();
}
#AfterMethod
public void tearDown()
{
driver.quit();
}
(or)
public static WebDriver driver;
#BeforeTest
public void preConfig()
{
if(browser.equals("firefox"))
{
System.setProperty("webdriver.gecko.driver","C:\\Program Files\\FireFox\\geckodriver-v0.24.0-win64\\geckodriver.exe");
driver=new FirefoxDriver();
}
if(browser.equals("chrome"))
{
System.setProperty("webdriver.chrome.driver", "C:\\Program Files\\Chrome\\chromedriver_win32\\chromedriver.exe");
driver=new ChromeDriver();
}
driver.get("http://desktop-g53h9ip:81/login.do");
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#AfterTest
public void postConfig()
{
driver.close();
}
It is better to instantiate browser once for a single test and 2nd approach is better approach for any kind of framework.
Following structure for TestNG annotations
#BeforeSuite
#BeforeTest
#BeforeClass
#BeforeMethod
#Test
#AfterMethod
#AfterClass
#AfterTest
#AfterSuite
Below is the code am trying to execute
Not sure why am getting [TestNG] No tests found. Nothing was run
if I remove the before class annotation method, it executes but fails due the dependency
public class TestNG_Practice3 {
static WebDriver driver ;
String url = "https://in.linkedin.com/";
#BeforeClass(description = "To open the browser")
public void openBrowser()
{ driver = new FirefoxDriver();
driver.get(url);
System.out.println("Browser got open");
}
#Test (dependsOnMethods ="openBrowser",description = "To signin")
public void login()
{
driver.manage().timeouts().implicitlyWait(2000, TimeUnit.SECONDS);
WebElement signin = driver.findElement(By.id("login-email"));
Assert.assertTrue(signin.isDisplayed());
WebElement password = driver.findElement(By.id("login-password"));
WebElement signinbutton = driver.findElement(By.id("login-submit"));
signin.sendKeys("xyz");
password.sendKeys("abc");
signinbutton.click();
Assert.assertTrue(driver.getCurrentUrl().contains("feed/"));
}
#Test(dependsOnMethods = "login")
public void logout()
{
WebElement meDropdown = driver.findElement(By.xpath("//*[#id=\"nav-settings__dropdown-trigger\"]/div/span[2]/li-icon/svg"));
meDropdown.click();
WebElement logout = driver.findElement(By.id("ember545"));
logout.click();
}
#AfterClass
public void closebrowser()
{
driver.quit();
}
}
Step-1 : Basic trial with Project Build,
public class TestNG_Demo {
#BeforeClass
public void openbrowser()
{
System.out.println("Browser got open");
}
#Test
public void testbrowser()
{
System.out.println("Test execution");
}
#AfterClass
public void closebrowser()
{
System.out.println("Browser got close");
}
}
So you will be have idea, Your project build get successful execution.
If you have maven project and Build did not get pass, you will be have trigger what is causing from maven build dependency.
Update
Step-2 : After tracing first trial
public class TestNG_Demo {
#Test
public void testbrowser()
{
WebDriver driver = new FirefoxDriver();
driver.get("http://google.com");
}
}
Remove dependsOnMethods ="openBrowser" because it's not a test method and will be execute before test without it
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();
}
}
Hi When i run the following testNG file as a standalone script if executes as expected.
public class TESTTNGClass {
WebDriver driver;
#Test
public void f() {
System.out.println("In Test");
}
#BeforeMethod
public void beforeMethod() {
System.out.println("Before Test");
}
#AfterMethod
public void afterMethod() {
System.out.println("After Test");
}
}
O/P:
Before Test
In Test
After Test
But why does the same not work when called from another class. Please help to achieve the same when triggered from another class. Following is the class calling the test class
public class TESTClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
TESTTNGClass t = new TESTTNGClass();
t.f();
}
}
O/P:
In Test
Here is the Answer to your Question:
In the process of understanding and experiment with Java & TestNG you have diminished the Annotation power of TestNG.
When you are executing TESTTNGClass.java as a TestNG Test all works well. No issues.
When you are executing TESTClass.java as a Java Application, Java only understands main() where you are creating an object of Class TESTTNGClass and then you are calling the method f(). As Java Compiler have have no idea of BeforeMethod, Test & AfterMethod Annotations of TestNG, it simply executes f() method, prints In Test and ends execution.
About how to do it:
Replace main() by some other name foo().
Bring f() from "TESTTNGClass" class into "TESTClass" class.
While you write "TESTClass" class extend "TESTTNGClass" class.
Execute "TESTClass.java" as a TestNG Test
Your Application will look like:
TESTTNGClass Class:
package Q44240531_TestNG_Main;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
public class TESTTNGClass
{
#BeforeMethod
public void beforeMethod() {
System.out.println("Before Test");
}
#AfterMethod
public void afterMethod() {
System.out.println("After Test");
}
}
TESTClass Class:
package Q44240531_TestNG_Main;
import org.testng.annotations.Test;
public class TESTClass extends TESTTNGClass {
#Test
public void f()
{
System.out.println("In Test");
}
}
Let me know if this Answers your Question.
public class TESTClass extends TESTTNGClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
TESTTNGClass t = new TESTTNGClass();
try{
t.f();
}catch (Exception e){
e.printStackTrace();
}
}
}
I am currently capturing screenshots on failure and success in TestNG by way of overriding the TestListenerAdapter methods onTestFailure, and onTestSuccess respectively. In order to do this you need to specify which driver you want to take a screenshot of.
My question: Is there a good way to capture screenshots when running tests in parallel on the method level?
In order to run tests in parallel, each individual test needs a unique driver instance. So, at any given time you have x number of driver instances running. When it comes time to capture a screenshot, how do you determine which driver to use?
Code excerpts below:
public class OnFailureListener extends TestListenerAdapter {
#Override
public void onTestFailure(ITestResult tr) {
Screenshots.captureScreenshot(tr);
super.onTestFailure(tr);
}
--
public static void captureScreenshot(ITestResult tr) {
WebDriver driver = TestClass.driver;
if (driver instanceof TakesScreenshot) {
String filename = "path/to/screenshot/file";
try {
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File(filename));
} catch (IOException e) { e.printStackTrace(); }
}
If you create a base test class with access to the driver, then that driver will always be the correct driver
The following will achieve this;
All test classes must extend a simple base test class;
public asbtract baseTestCase() {
private WebDriver driver;
public WebDriver getDriver() {
return driver;
}
#BeforeMethod
public void createDriver() {
driver=XXXXDriver();
}
#AfterMethod
public void tearDownDriver() {
if (driver != null){
try{
driver.quit();
}
catch (WebDriverException e) {
System.out.println("***** CAUGHT EXCEPTION IN DRIVER TEARDOWN *****");
System.out.println(e);
}
}
}
In your listener, you need to access the base class:
public class ScreenshotListener extends TestListenerAdapter {
#Override
public void onTestFailure(ITestResult result){
Object currentClass = result.getInstance();
WebDriver webDriver = ((BaseTest) currentClass).getDriver();
if (webDriver != null){
File f = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);
//etc.
}
}
}