跨不同的类访问@BeforeTest和@AfterClass(TestNG)中的变量?

问题描述 投票:0回答:3

我正在使用 Java 和 TestNG 框架为我的公司编写一些 selenium 自动化 UI 测试。我在

Base
类中定义驱动程序,并且我想在
@BeforeTest
中实际初始化驱动程序并在
@AfterTest
方法中退出它。假设它们位于不同的类中,Java 的方法是什么?我知道如何让它在同一个班级中工作,但不能在不同的班级中工作。这是我的
Base.java
文件:

public class Base {

        public static WebDriver driver = null;
        public WebDriver getDriver() {
            driver = new ChromeDriver();
            return driver;
        }
}

现在,我想要一个单独的安装类和一个单独的拆卸类。如果我要在同一个

@Test
中定义所有这些,我会这样做:

@Test
public void testOne() {

    Base b = new Base();
    WebDriver driver = b.getDriver();

    // Do test-y things here. 

    driver.quit();
}

我该如何设置?尝试学习正确的方法来做到这一点,而不是一起破解某些东西。如果需要的话我还可以提供更多信息。谢谢!

java selenium testng
3个回答
6
投票

使用继承。

public class TestBase {

    protected WebDriver driver;

    @BeforeClass
    public void setUp(){
        System.out.println("I am in setUp method.");

        //WebDriver instantiation etc.
        System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized", "--disable-cache");
        driver = new ChromeDriver(options);
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    }

    @AfterClass
    public void tearDown(){
        System.out.println("I am in tearDown method.");

        //You can clean up after tests.
        driver.close();
    }
}

然后就可以使用继承了。注意

extends
关键字:

public class ParticularTest extends TestBase {

   @Test
   public void testMethod() {
       System.out.println("I am in testMethod.");

       //Your driver from TestBase is accessible here.
       //Your assertions come here.
   }
}

稍后您可以执行

ParticularTest.java
。 输出:

I am in setUp method.
I am in testMethod.
I am in tearDown method.

2
投票

我建议您不要在测试中使用这种实例化网络驱动程序的机制。根据定义,

@BeforeTest
预计每个<test>标签都会被调用
ONLY ONCE
。因此,如果您的 TestNG 套件 xml 文件有类似这样的内容

<test name="MyTests">
    <classes>
        <class name="com.foo.Test1"/>
        <class name="com.foo.Test2"/>
    </classes>
</test>

并且如果

com.foo.Test1
com.foo.Test2
都扩展了
TestBase
类,那么
@Test
类中的
com.foo.Test2
方法在访问
NullPointerException
对象时必然会命中
driver
,因为你的
@BeforeTest
setup()
中带注释的
TestBase
方法将仅执行一次(对于
Test1
),并且对于 Test 不会执行
,因为这两个类都从同一个基类扩展。

我建议您使用this(这是我的博客)之类的东西来进行网络驱动程序实例化。


0
投票
    I  have a similar issue and need help to understand if my code needs any restructuring.
    parent class
    ------------
    package selenium.setup;
    
    import java.util.concurrent.TimeUnit;
    
    import org.openqa.selenium.WebDriver;
    import org.testng.annotations.AfterClass;
    import org.testng.annotations.AfterTest;
    import org.testng.annotations.BeforeClass;
    import org.testng.annotations.BeforeSuite;
    import org.testng.annotations.Parameters;
    
    public class SeleniumBaseTest {
        protected final static ThreadLocal<WebDriver> webDriver = new ThreadLocal<> 
        ();
            
        @BeforeClass
        @Parameters({"browser","baseURL"})
        public void Setup(String browser, String baseURL) throws Exception{
            webDriver.set(BrowserManager.doBrowserSetup(browser));
            System.out.println("Before Test Thread ID: 
            "+Thread.currentThread().getId());
            //get URL
            webDriver.get().get(baseURL);
            webDriver.get().manage().window().maximize();
            webDriver.get().manage().deleteAllCookies();
            webDriver.get().manage().timeouts().implicitlyWait(30, 
            TimeUnit.SECONDS);
        }
    
        @AfterClass
        public void tearDown(){
            webDriver.get().quit();
            System.out.println("After Test Thread ID: 
            "+Thread.currentThread().getId());
            webDriver.remove();
        }
    }`
    
    Child class
    -----------
    `package selenium.trials;
    
    import java.time.Duration;
    
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.interactions.Actions;
    import org.testng.ITestContext;
    import org.testng.annotations.AfterTest;
    import org.testng.annotations.BeforeTest;
    import org.testng.annotations.Test;
    
    import selenium.setup.SeleniumBaseTest;
    import selenium.utils.WebElementUtility;
    
    public class SeleniumDragnDrop extends SeleniumBaseTest{
        Logger logger;
        WebDriver driver;
        
        @BeforeTest(alwaysRun=true)
        public void beforeTest(ITestContext testContext){
          logger = LogManager.getLogger(this.getClass());
          driver = webDriver.get();
          
          logger.info("In dragNDrop beforeTest: Thread ID: 
          "+Thread.currentThread().getId());
        }
        
        @Test
        public void dragNDrop() throws InterruptedException {
            logger.info("In dragNDrop Thread ID: "+Thread.currentThread().getId());
            
        WebElementUtility.clickOn(driver,driver.findElement(By.linkText("Drag and 
        Drop")), Duration.ofSeconds(15));
            
        WebElement source = driver.findElement(By.id("column-a"));
        WebElement dest = driver.findElement(By.id("column-b"));
        Actions action = new Actions(driver);
        action.dragAndDrop(source, dest).build().perform();
        logger.info("After dragNDrop Thread ID: "+Thread.currentThread().getId());
        }
        
        @AfterTest
        public void tearDown() {
        logger.info("In dragNDrop tearDown : Thread ID: 
        "+Thread.currentThread().getId());
        }
    }`
    
package selenium.trials;

import java.awt.AWTException;
import java.time.Duration;
import java.util.concurrent.TimeUnit;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.ITestContext;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import selenium.setup.SeleniumBaseTest;
import selenium.utils.WebElementUtility;

public class SeleniumAlerts extends SeleniumBaseTest{
    Logger logger;
    WebDriver webDriver;
    
    @BeforeMethod
    public void beforeTest(ITestContext testContext){
      logger = LogManager.getLogger(this.getClass());
      //webDriver = driver.get();
      logger.info("In testAlerts beforeMethod: Thread ID: "+Thread.currentThread().getId());
      logger.info(" Driver " + driver.get().getCurrentUrl());
    }
    
    @Test
    public void testAlerts() throws InterruptedException {
        logger = LogManager.getLogger(this.getClass());
        logger.info("In testAlerts Thread ID: "+Thread.currentThread().getId());
        Thread.sleep(2000);
        //driver = webDriver.get();
        
        try {
        WebElementUtility.clickOn(driver.get(),driver.get().findElement(By.linkText("JavaScript Alerts")), Duration.ofSeconds(15));
        }catch(org.openqa.selenium.StaleElementReferenceException ex)
        {
            System.out.println(" current URL  " + driver.get().getCurrentUrl());
            WebElementUtility.clickOn(driver.get(),driver.get().findElement(By.linkText("JavaScript Alerts")), Duration.ofSeconds(15));
        }
        
        WebElement ele = driver.get().findElement(By.xpath("//button[text()='Click for JS Alert']")); 
        WebElementUtility.clickOnAlert(driver.get(),ele, Duration.ofSeconds(20),true);
        
        WebElementUtility.clickOnAlert(driver.get(),driver.get().findElement(By.xpath("//button[text()='Click for JS Confirm']")), Duration.ofSeconds(20),false);
        clickOnPrompt(driver.get(),driver.get().findElement(By.xpath("//button[text()='Click for JS Prompt']")), Duration.ofSeconds(20),false);
        logger.info("In testAlerts Thread ID: "+Thread.currentThread().getId());
        //driver.get().quit();
    }
    
    @AfterMethod
    public void setDown() {
        logger.info("In testAlerts setDown : Thread ID: "+Thread.currentThread().getId());
        //driver.get().quit();
    }
    testng.xml
    ---------
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="TestSuite" thread-count="2" parallel="classes">
    <parameter name="browser" value="Chrome"/>
    <parameter name="baseURL" value="https://the-internet.herokuapp.com"/>
    
    <test name="SeleniumTrials"  preserve-order="true">
        <classes>
            <class name="selenium.trials.SeleniumDragnDrop"/>
            <class name="selenium.trials.SeleniumAlerts"/>
        </classes>
    </test>
    </suite>
    
    Log - The issue is for the second test, the browser does not close. that means the @AfterClass is not called. Its also evident from the fact that the logger.info for this test also is not logged.
    ---
    
    17:23:10.015 [TestNG-test=SeleniumTrials-2] INFO  selenium.trials.SeleniumAlerts - Before Class: Setup Thread ID: 23
    17:23:36.591 [TestNG-test=SeleniumTrials-2] INFO  selenium.trials.SeleniumAlerts - Before Class: Setup Thread ID: 24
    17:23:40.558 [TestNG-test=SeleniumTrials-1] INFO  selenium.trials.SeleniumDragnDrop - Before Class: Setup Thread ID: 23
    17:24:15.498 [TestNG-test=SeleniumTrials-2] INFO  selenium.trials.SeleniumAlerts - In testAlerts beforeMethod: Thread ID: 24
    17:24:15.518 [TestNG-test=SeleniumTrials-2] INFO  selenium.trials.SeleniumAlerts -  Driver https://the-internet.herokuapp.com/
    17:24:19.681 [TestNG-test=SeleniumTrials-2] INFO  selenium.trials.SeleniumAlerts - In testAlerts Thread ID: 24
    17:24:23.108 [TestNG-test=SeleniumTrials-1] INFO  selenium.trials.SeleniumDragnDrop - In dragNDrop beforeMethod: Thread ID: 23
    17:24:23.112 [TestNG-test=SeleniumTrials-1] INFO  selenium.trials.SeleniumDragnDrop - In dragNDrop Thread ID: 23
    17:24:28.017 [TestNG-test=SeleniumTrials-1] INFO  selenium.trials.SeleniumDragnDrop - After dragNDrop Thread ID: 23
    17:24:28.019 [TestNG-test=SeleniumTrials-1] INFO  selenium.trials.SeleniumDragnDrop - In dragNDrop setDown : Thread ID: 23
    17:24:40.756 [TestNG-test=SeleniumTrials-2] INFO  selenium.trials.SeleniumAlerts - In testAlerts Thread ID: 24
    17:24:40.760 [TestNG-test=SeleniumTrials-2] INFO  selenium.trials.SeleniumAlerts - In testAlerts setDown : Thread ID: 24
    17:24:55.176 [TestNG-test=SeleniumTrials-2] INFO  selenium.trials.SeleniumAlerts - After Class: Setup Thread ID: 24
© www.soinside.com 2019 - 2024. All rights reserved.