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();
}
}
}
Related
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
I have a fairly simple Cucumber test framework with a feature file, a step definitions file, and a test runner class that looks like this:
#RunWith(Cucumber.class)
#CucumberOptions(features = "src/test/java/com/tests/cucumber/features/ui/ExampleTest.feature",
glue = { "com.tests.cucumber.stepdefinitions" },
)
public class ExampleTestRunner {
}
This runs a scenario in the feature file just fine. Now I want to add a Before and After hook to do some setup and teardown, but I can't for the like of me get the hooks to run. I've tried adding the hooks to the ExampleTestRunner and to the StepDefinition class, but they never run. Where should I put these hooks? At the moment, the hooks just look like this, but I'll add content to them once I've worked this out!
package com.tests.cucumber.stepdefinitions;
import cucumber.api.java.After;
import cucumber.api.java.Before;
public class StepDefinitions {
#Before
public void before() {
System.out.println("starting before()");
}
}
Thanks for any help.
I am a little hesitant to answer this question even though I managed to get this to work. As far as I can tell, the problem was that I had added the Before and After methods in classes that were extended by other classes. In this situation, the tests would not run. I had to add the Before and After methods to a class that was not extended.
It feels like this is similar to the situation in which if you specify a step definition in a class that is extended by another class, then the step definition is considered to have a duplicate definition. Do I have the correct diagnosis here?
I use like this;
Runner Class:
#RunWith(Cucumber.class)
#CucumberOptions(
features = {"src\\test\\features\\ui_features"},
glue = {"com\\base\\tm\\auto_reg\\tests\\ui_tests\\price_features"},
plugin = {"com.cucumber.listener.ExtentCucumberFormatter:"}
)
public class PriceFeatureRunner {
#BeforeClass
public static void setup() {
RunnerUtil.setup(PriceFeatureRunner.class);
}
#AfterClass
public static void teardown() {
RunnerUtil.teardown();
}
}
RunnerUtil.java:
public class RunnerUtil {
public static void setup(Class<?> clazz) {
String reportPath = "target/cucumber-reports/" + clazz.getSimpleName().split("_")[0] + "_report.html";
ExtentProperties extentProperties = ExtentProperties.INSTANCE;
extentProperties.setReportPath(reportPath);
}
public static void teardown() {
UiHooks uiHooks = new UiHooks();
uiHooks.afterScenario();
ExtentReportConfiguration.configureExtentReportTeardown();
}
}
UiHooks.java
public class UiHooks implements HookHelper {
public static final String BASE_URL = "https://www.stackoverfow.com/";
private Scenario scenario;
#Override
#Before
public void beforeScenario(Scenario scenario) {
this.scenario = scenario;
Reporter.assignAuthor(System.getProperty("user.name"));
}
#Override
#After
public void afterScenario() {
if (HookUtil.driver != null) {
HookUtil.driver.quit();
}
if (HookUtil.seleniumBase != null) {
HookUtil.seleniumBase.stopService();
}
}
#Override
#After
public void afterTest() {
if (HookUtil.driver != null) {
HookUtil.driver.quit();
}
if (HookUtil.seleniumBase != null) {
HookUtil.seleniumBase.stopService();
}
}
}
HookHelper.Java
public interface HookHelper {
#Before
void beforeScenario(Scenario scenario);
#After
void afterScenario();
void afterTest();
}
I'm new to Selenium Webdriver, I have a few question :
First, I have 2 class, 'Login.java' and 'SelectCity.java
Class 1 : Login.java
invalidLogin
validLogin
Class 2 : SelectCity.java
For now, in Login.java I wrote
#After
public void tearDown() throws Exception {
driver.close();
}
which mean the browser will closed after finish run right?
Here is my question :
How to make after I run validLogin, it will continue to run the next class (SelectCity.java)?
Is it possible to do that?
How to make last browser (which test valid login) didn't get close?
My current Login.java class :
public class Login extends SelectCityAfterLogin{
private WebDriver driver;
private String baseUrl;
private StringBuffer verificationErrors = new StringBuffer();
#Before
public void setUp() throws Exception {
driver = new FirefoxDriver();
baseUrl = "http://mysite/";
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#Test
public void testLoginInvalidPass() throws Exception {
driver.get(baseUrl + "/mysite/login.aspx");
driver.findElement(By.id("txtUsername")).sendKeys("user1");
driver.findElement(By.id("txtPassword")).sendKeys("somePassword");
driver.findElement(By.id("lbLogin")).click();
try {
assertEquals("Invalid User or Password", driver.findElement(By.id("lblError")).getText());
} catch (Error e) {
verificationErrors.append(e.toString());
}
}
#Test
public void testLoginInvalidUsername() throws Exception {
driver.get(baseUrl + "/mysite/login.aspx");
driver.findElement(By.id("txtUsername")).sendKeys("username");
driver.findElement(By.id("txtPassword")).sendKeys("somepassword");
driver.findElement(By.id("lbLogin")).click();
try {
assertEquals("Invalid User or Password", driver.findElement(By.id("lblError")).getText());
} catch (Error e) {
verificationErrors.append(e.toString());
}
}
#Test
public void testLoginNoUsername() throws Exception {
driver.get(baseUrl + "/mysite/login.aspx");
driver.findElement(By.id("txtUsername")).sendKeys("");
driver.findElement(By.id("txtPassword")).sendKeys("somePassword");
driver.findElement(By.id("lbLogin")).click();
try {
assertEquals("Please fill username and password.", driver.findElement(By.id("lblError")).getText());
} catch (Error e) {
verificationErrors.append(e.toString());
}
}
#Test
public void testLoginNoPassword() throws Exception {
driver.get(baseUrl + "/mysite/login.aspx");
driver.findElement(By.id("txtUsername")).sendKeys("username");
driver.findElement(By.id("txtPassword")).sendKeys("");
driver.findElement(By.id("lbLogin")).click();
try {
assertEquals("Please fill username and password.", driver.findElement(By.id("lblError")).getText());
} catch (Error e) {
verificationErrors.append(e.toString());
}
}
#Test
public void testLoginValid() throws Exception{
//SelectRoleAfterLogin selectRole = SelectRoleAfterLogin();
driver.get(baseUrl + "/mysite/login.aspx");
driver.findElement(By.id("txtUsername")).sendKeys("myUsername");
driver.findElement(By.id("txtPassword")).sendKeys("password");
driver.findElement(By.id("lbLogin")).click();
Thread.sleep(3000);
}
}
Thx
Yes you can run selectcity after login
You should Extend your First class to Second class
In your Login.java extend it to selectcity java like below
Public class login extends Selectcity {
After your validlogin
create a new instance for selectcity (If you are using #test, create the below in that)
selectcity test = new selectcity()
Once after your valid login do the following
test.(will fetch you the methods available in selectcity.java)
By this way you can call once class to another.
Let me know if this helps
UPDATE :
if selectcityAfterlogin in public class Login extends **SelectCityAfterLogin** is your second class name, then you are creating an incorrect object i guess
In your public login class please check whether your are extending the proper second class name
In #test method
#Test
public void testLoginValid() throws Exception{
//SelectRoleAfterLogin selectRole = SelectRoleAfterLogin();
it should be
SelectCityAfterLogin selectrole = new SelectCityAfterLogin()
selectrole.(will fetch you the methods of second city)
Please let me know if this helps.
One better solution would be to create multiple methods than multiple #test. You can call these to single #test suite.
I am assuming, you have 2 classes 'Login.java' and 'SelectCity.java'
as follows:
Class 1 : Login.java
public void invalidLogin (WebDriver driver){
//some operations
}
public void validLogin (WebDriver driver){
//some operations
}
Class 2 : SelectCity.java
public void selectCity (Webdriver Driver){
//some operations
}
Class 3: LoginAndSelectCity.java
public static void main(String args []){
WebDriver driver = new FirefoxDriver();
Login.validLogin(driver);
SelectCity.selectCity(driver);
}
If all classes should be in same package then only it works else you need to import packages or create new child to do inheritance of the classes.
I'm using JUnit and Selenium. I would like to log in once to a web page, after run I run two test cases, without opening a new browser/session. If I do the "logging in" in setUp() method, then this called at every time before the test cases. How can I use only one setUp() method for all of my test cases?
I think it could be achieved in the following manner
package com.java;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;
public class TestAnnt {
public static Selenium sel;
#BeforeClass
public static void beforeClass() {
sel = new DefaultSelenium("localhost", 5555, "*firefox",
"http://www.google.com");
sel.start();
System.out.println("Before Class");
}
#Before
public void beforeTest() {
System.out.println("Before Test");
// Actions before a test case is executed
}
#Test
public void testone() {
sel.open("/");
sel.waitForPageToLoad("30000");
System.out.println("Test one");
// Actions of test case 1
}
#Test
public void testtwo() {
sel.open("http://au.yahoo.com");
sel.waitForPageToLoad("30000");
System.out.println("test two");
// Actions of test case 2
}
#After
public void afterTest() {
System.out.println("after test");
// Actions after a test case is executed
}
#AfterClass
public static void afterClass() {
sel.close();
sel.stop();
sel.shutDownSeleniumServer();
System.out.println("After Class");
}
}
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 {
}
}