Hi I am practicing testng and I have a simple class as follows:
public class testclass1 {
#Test
public void firstMethod() {
System.out.println("first");
}
#Test
public void secondMethod() {
System.out.println("second");
}
#Test
#BeforeSuite
public void thirdMethod() {
System.out.println("third- before suite");
}
#Test
#AfterClass
public void fourthMethod() {
System.out.println("fourth- after class");
}
}
On execution, the results are
[RemoteTestNG] detected TestNG version 7.3.0
third- before suite
first
fourth- after class
second
third- before suite
fourth- after class
I am confused. Why is before suite and after class method invoked twice?
Just remove #Test annotation in the #AfterClass and #BeforeSuite:
public class testclass1 {
#Test
public void firstMethod() {
System.out.println("first");
}
#Test
public void secondMethod() {
System.out.println("second");
}
#BeforeSuite
public void thirdMethod() {
System.out.println("third- before suite");
}
#AfterClass
public void fourthMethod() {
System.out.println("fourth- after class");
}
}
Output:
third- before suite
first
second
fourth- after class
Related
after field one testcase, successful test Case skiped why ? how can i fix it?
public class RadioButtonTests {
#BeforeSuite()
public void ConfigTests(){
open("https://demoqa.com/radio-button");
}
#Test
public void RadioButtonYes(){//successful
$(withText("Yes")).click();
Assert.assertTrue($(byId("yesRadio")).isDisplayed());
}
#Test
public void RadioButtonNo(){//field
Assert.assertTrue($(byId("noRadio")).isEnabled());
}
#Test
public void Ra(){//field
$(withText("Yes")).shouldNot(Condition.visible);
}
#Test
public void Radio(){//successful
$(withText("Yes")).shouldBe(Condition.visible);
Assert.assertTrue($(byId("yesRadio")).isSelected());
}
}
enter image description 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");
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 want to Print the name of Currently Executing Test Method in #BeforeMethod and #AfterMethod using testng.
Like :
public class LoginTest {
#Test
public void Test01_LoginPage(){
//Some Code here
}
#Test
public void Test02_LoginPage(){
//Some Code Here
}
#BeforeMethod
public void beforeTestCase(){
//Print Test method name which is going to execute.
}
#AfterMethod
public void AfterTestCase(){
//Print Test method name which is executed.
}
}
From the documentation:
public class LoginTest {
#Test
public void Test01_LoginPage() {
//Some Code here
}
#Test
public void Test02_LoginPage() {
//Some Code Here
}
#BeforeMethod
public void beforeTestCase(Method m) {
System.out.println(m.getName());
}
#AfterMethod
public void AfterTestCase(Method m) {
System.out.println(m.getName());
}
}
You can use listeners like this link. Important code from the link:-
// This belongs to IInvokedMethodListener and will execute before every method including //#Before #After #Test
public void beforeInvocation(IInvokedMethod arg0, ITestResult arg1) {
String textMsg = "About to begin executing following method : " + returnMethodName(arg0.getTestMethod());
Reporter.log(textMsg, true);
}
// This belongs to IInvokedMethodListener and will execute after every method including #Before #After #Test
public void afterInvocation(IInvokedMethod arg0, ITestResult arg1) {
String textMsg = "Completed executing following method : " + returnMethodName(arg0.getTestMethod());
Reporter.log(textMsg, true);
}
// This will return method names to the calling function
private String returnMethodName(ITestNGMethod method) {
return method.getRealClass().getSimpleName() + "." + method.getMethodName();
}
The below example explains how you can get the method name and class name of your #test method in before method and After method
#Test
public void exampleTest(){
}
#BeforeMethod
public void beforemethod(Method method){
//if you want to get the class name in before method
String classname = getClass().getSimpleName();
//IF you want to get the method name in the before method
String methodName = method.getName()
//this will return you exampleTest
}
#AfterMethod
public void beforemethod(Method method){
//if you want to get the class name in After method
String classname = getClass().getSimpleName();
//IF you want to get the method name in the After method
String methodName = method.getName()
//this will return you exampleTest
}
Is there a way to invoke a method after all #After annotated methods of a test method had been run?
I need this for a special framework for my company.
In testng i can use the afterInvocation method, which is called after every configuration method. Is there some alternative in JUnit?
A rule will run after all the #Afters. The ExternalResource could be abused in order to do what you want:
public class VerifyTest {
#Rule public ExternalResource externalResource = new ExternalResource() {
public void after() {
System.out.println("ExternalResource.after");
}
};
#After
public void after1() {
System.out.println("after1");
}
#After
public void after2() {
System.out.println("after2");
}
#Test
public void testVerify throws IOException {
}
}