【问题标题】:Cannot run parallel tests with @Factory testng annotation on java无法在 java 上使用 @Factory testng 注释运行并行测试
【发布时间】:2018-02-07 14:35:33
【问题描述】:

所以我使用@Factory 对 5 封不同的电子邮件运行一项测试,但我得到 error number of arguments 异常,并且在控制台上看不到完整的错误跟踪。我使用TestNG。这是我的代码:

package com.task.lab.facadetask;

public class GmailTest {
    private WebDriver driver;
    private static List<User> usersList;
    static List<TestMessage> mess;

    public GmailTest(){}


    @Factory(dataProviderClass = GmailTest.class, dataProvider = "getData")
    public GmailTest(WebDriver driver,List<User> usersList, List<TestMessage> mess ){
        this.driver = driver;
        GmailTest.usersList = usersList;
        GmailTest.mess = mess;
    }

    @BeforeMethod
    public void setUpDriver(){
        driver = DriverObject.getDriver();
    }

    @DataProvider
    public static Object[][] getData() {
        File usersXml = new File("src\\\\main\\\\java\\\\com\\\\task\\\\lab\\\\facadetask\\\\testdata\\\\users.xml");

        try {
            usersList = JAXB.unmarshal(usersXml);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        TestMessages messages =  UnMarshell.unmarshaller();
        assert messages != null;
        mess = messages.getTestMessages();
        return new Object[][]{
                {mess.get(0), usersList.get(0)},
                {mess.get(1), usersList.get(1)},
                {mess.get(2), usersList.get(2)},
        };
    }

    @Test
    public void testGmail(TestMessage message, User users) {
        String gmailURL = "https://accounts.google.com/signin";
        driver.get(gmailURL);
        Login loginPage = new Login();
        loginPage.login(users.getEmail(), users.getPassword());
        GmailMessage gmailPage = new GmailMessage();
        gmailPage.sendMessage(message.getReceiver(), message.getSubject(), message.getMessage());
        gmailPage.removeMessage();
        Assert.assertTrue(gmailPage.isRemoved());
    }
    @AfterMethod
    public void quitBrowser(){
        try{
            driver.close();
        }finally{
            driver.quit();
        }
    }
}

我的假设是它可能是由于将原始的非静态用户和消息列表更改为静态引起的,但 DataProvider 方法需要是静态的。有人可以指导我做错什么吗? UPD:所以,我按照 Krishnan 的建议删除了 @BeforeMethod 并将驱动程序包含在 @DataProvider 中,但它给了我同样的错误,错误的参数数量。下面是 DataProvider 现在开始的内容:

@DataProvider
public static Object[][] getData() {
    driver = DriverObject.getDriver();
    File usersXml = new File   //The rest remains the same

另外,我尝试在 BeforeMethod 中初始化驱动程序,但在这种情况下,Test 看不到它。它看起来像这样:

@BeforeMethod
public void setUpDriver(){
    WebDriver driver = DriverObject.getDriver();
}

也许有人可以为我提供一个有效的 Factory 类似物,以便我可以同时运行 5 个并行测试?我愿意接受建议。

【问题讨论】:

    标签: java testng factory


    【解决方案1】:

    您的工厂方法被定义为接受 3 个参数。

    @Factory(dataProviderClass = GmailTest.class, dataProvider = "getData")
    public GmailTest(WebDriver driver,List<User> usersList, List<TestMessage> mess ){
        this.driver = driver;
        GmailTest.usersList = usersList;
        GmailTest.mess = mess;
    }
    

    您的数据提供者仅提供 2 个参数。您的数据提供商未提供 WebDriver。

    您可以执行以下操作之一:

    • 通过调用DriverObject.getDriver() 增强您的数据提供程序以包含WebDriver 对象并删除您的@BeforeMethod 方法(或)
    • 将构造函数的签名更改为不接受 WebDriver 实例,但通过 @BeforeMethod 初始化类的 WebDriver 实例。

    这应该可以解决您的问题。

    编辑:问题已更新。所以也更新我的答案。

    看问题的更新,答案在高层次上还是一样的。现在还包括一个示例,它解释了答案。

    模拟 User 类的外观

    import java.util.ArrayList;
    import java.util.List;
    
    public class User {
        private String name;
    
        public User(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public static List<User> newUsers(String... names) {
            List<User> users = new ArrayList<>();
            for (String name : names) {
                users.add(new User(name));
            }
            return users;
        }
    }
    

    模拟 TestMessage 类的样子

    import java.util.ArrayList;
    import java.util.List;
    import java.util.UUID;
    
    public class TestMessage {
        private String text;
    
        public TestMessage(String text) {
            this.text = text;
        }
    
        public String getText() {
            return text;
        }
    
        public static List<TestMessage> newMessages(int howMany) {
            List<TestMessage> msgs = new ArrayList<>();
            for (int i = 0; i < howMany; i++) {
                msgs.add(new TestMessage(UUID.randomUUID().toString()));
            }
            return msgs;
        }
    }
    

    测试类应该是这样的

    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.firefox.FirefoxDriver;
    import org.testng.Assert;
    import org.testng.annotations.AfterClass;
    import org.testng.annotations.DataProvider;
    import org.testng.annotations.Factory;
    import org.testng.annotations.Test;
    
    import java.util.Collections;
    import java.util.List;
    
    public class GmailTest {
        private WebDriver driver;
        private List<User> users;
        private List<TestMessage> testMessages;
    
        @Factory(dataProvider = "getData")
        public GmailTest(WebDriver driver, List<User> users, List<TestMessage> testMessages) {
            this.driver = driver;
            this.users = users;
            this.testMessages = testMessages;
        }
    
        @Test
        public void testMethod() {
            Assert.assertNotNull(driver);
            Assert.assertNotNull(users);
            Assert.assertNotNull(testMessages);
        }
    
        @AfterClass
        public void cleanupDrivers() {
            if (driver != null) {
                driver.quit();
            }
        }
    
        @DataProvider(name = "getData")
        public static Object[][] getData() {
            List<User> users = User.newUsers("Jack", "Daniel", "John");
            int size = users.size();
            List<TestMessage> testMessages = TestMessage.newMessages(size);
            Object[][] data = new Object[size][1];
            for (int i = 0; i < size; i++) {
                data[i] = new Object[]{new FirefoxDriver(), Collections.singletonList(users.get(i)),
                        Collections.singletonList(testMessages.get(0))};
            }
            return data;
        }
    }
    

    这是执行日志

    1518271888011   geckodriver INFO    geckodriver 0.19.1
    1518271888131   geckodriver INFO    Listening on 127.0.0.1:14727
    1518271888627   mozrunner::runner   INFO    Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "-marionette" "-profile" "/var/folders/mj/81r6v7nn5lqgqgtfl18spfpw0000gn/T/rust_mozprofile.5mkpumai11hO"
    1518271889362   Marionette  INFO    Enabled via --marionette
    2018-02-10 19:41:30.336 plugin-container[53151:969522] *** CFMessagePort: bootstrap_register(): failed 1100 (0x44c) 'Permission denied', port = 0xad33, name = 'com.apple.tsm.portname'
    See /usr/include/servers/bootstrap_defs.h for the error codes.
    1518271890773   Marionette  INFO    Listening on port 52891
    1518271890793   Marionette  WARN    TLS certificate errors will be ignored for this session
    Feb 10, 2018 7:41:30 PM org.openqa.selenium.remote.ProtocolHandshake createSession
    INFO: Detected dialect: W3C
    1518271890961   geckodriver INFO    geckodriver 0.19.1
    1518271891060   geckodriver INFO    Listening on 127.0.0.1:6639
    2018-02-10 19:41:31.225 plugin-container[53152:969613] *** CFMessagePort: bootstrap_register(): failed 1100 (0x44c) 'Permission denied', port = 0xaa37, name = 'com.apple.tsm.portname'
    See /usr/include/servers/bootstrap_defs.h for the error codes.
    1518271891259   mozrunner::runner   INFO    Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "-marionette" "-profile" "/var/folders/mj/81r6v7nn5lqgqgtfl18spfpw0000gn/T/rust_mozprofile.npquNnysdwGI"
    1518271891832   Marionette  INFO    Enabled via --marionette
    2018-02-10 19:41:32.786 plugin-container[53155:969741] *** CFMessagePort: bootstrap_register(): failed 1100 (0x44c) 'Permission denied', port = 0xab3f, name = 'com.apple.tsm.portname'
    See /usr/include/servers/bootstrap_defs.h for the error codes.
    1518271893243   Marionette  INFO    Listening on port 53150
    1518271893342   Marionette  WARN    TLS certificate errors will be ignored for this session
    Feb 10, 2018 7:41:33 PM org.openqa.selenium.remote.ProtocolHandshake createSession
    INFO: Detected dialect: W3C
    1518271893499   geckodriver INFO    geckodriver 0.19.1
    1518271893590   geckodriver INFO    Listening on 127.0.0.1:48408
    2018-02-10 19:41:33.681 plugin-container[53156:969822] *** CFMessagePort: bootstrap_register(): failed 1100 (0x44c) 'Permission denied', port = 0x7c37, name = 'com.apple.tsm.portname'
    See /usr/include/servers/bootstrap_defs.h for the error codes.
    1518271893810   mozrunner::runner   INFO    Running command: "/Applications/Firefox.app/Contents/MacOS/firefox-bin" "-marionette" "-profile" "/var/folders/mj/81r6v7nn5lqgqgtfl18spfpw0000gn/T/rust_mozprofile.65SomKttNwQP"
    1518271894377   Marionette  INFO    Enabled via --marionette
    2018-02-10 19:41:35.326 plugin-container[53159:969958] *** CFMessagePort: bootstrap_register(): failed 1100 (0x44c) 'Permission denied', port = 0x1523b, name = 'com.apple.tsm.portname'
    See /usr/include/servers/bootstrap_defs.h for the error codes.
    1518271895785   Marionette  INFO    Listening on port 53451
    1518271895824   Marionette  WARN    TLS certificate errors will be ignored for this session
    Feb 10, 2018 7:41:35 PM org.openqa.selenium.remote.ProtocolHandshake createSession
    INFO: Detected dialect: W3C
    [GFX1-]: Receive IPC close with reason=AbnormalShutdown
    1518271896172   addons.xpi  WARN    Exception running bootstrap method shutdown on activity-stream@mozilla.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIObserverService.removeObserver]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: resource://activity-stream/lib/SnippetsFeed.jsm :: uninit :: line 125"  data: no] Stack trace: uninit()@resource://activity-stream/lib/SnippetsFeed.jsm:125 < onAction()@resource://activity-stream/lib/SnippetsFeed.jsm:141 < _middleware/</<()@resource://activity-stream/lib/Store.jsm:51 < Store/this[method]()@resource://activity-stream/lib/Store.jsm:30 < uninit()@resource://activity-stream/lib/Store.jsm:153 < uninit()@resource://activity-stream/lib/ActivityStream.jsm:278 < uninit()@resource://gre/modules/addons/XPIProvider.jsm -> jar:file:///Applications/Firefox.app/Contents/Resources/browser/features/activity-stream@mozilla.org.xpi!/bootstrap.js:80 < shutdown()@resource://gre/modules/addons/XPIProvider.jsm -> jar:file:///Applications/Firefox.app/Contents/Resources/browser/features/activity-stream@mozilla.org.xpi!/bootstrap.js:196 < callBootstrapMethod()@resource://gre/modules/addons/XPIProvider.jsm:4406 < observe()@resource://gre/modules/addons/XPIProvider.jsm:2270 < GeckoDriver.prototype.quit()@driver.js:3381 < despatch()@server.js:560 < execute()@server.js:534 < onPacket/<()@server.js:509 < onPacket()@server.js:508 < _onJSONObjectReady/<()@transport.js:500
    
    ===============================================
    Default Suite
    Total tests run: 3, Failures: 0, Skips: 0
    ===============================================
    
    
    Process finished with exit code 0
    

    【讨论】:

    • 没有帮助,我会尝试从测试中完全删除驱动程序,看看效果如何。
    • @annabretsko - 你申请了什么,你得到了什么错误信息?你能帮忙分享一下吗?
    • @annabretsko - 我已经更新了我的答案并包含了一个完整的示例。
    • 在我的情况下,将工厂和数据提供者分开并包括 suite.xml 就可以了。但是谢谢,这是一个很好的例子。
    猜你喜欢
    • 2019-08-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-14
    • 1970-01-01
    • 2017-11-04
    • 2021-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多