Некоторые тестовые прогоны дают мне параллельное исключение с selenium TestNG, как это исправить?

#java #selenium #cucumber #testng #java.util.concurrent

#java #селен #огурец #testng #java.util.concurrent

Вопрос:

Когда я запускаю свои тестовые примеры с cucumber textNg на jenkins с maven, не всегда, но иногда это выдает ошибку java.util.concurrent.Ex. , можете ли вы мне помочь? Некоторые из моих методов синхронизированы, так может быть? Мне нужно использовать synchronized, чтобы мои методы работали правильно.

Это мой тестовый xml

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Suite" data-provider-thread-count="8"
    thread-count="1" parallel="tests">
    <listeners>
        <listener
            class-name="com.oneapi.ta.oneapihub.listeners.TestNGListener" />
    </listeners>

    <test name="Firefox">
        <parameter name="browser" value="firefox"></parameter>
        <classes>
            <class
                name="com.oneapi.ta.oneapihub.runners.OneApiHubTestAutomationRunnerTest" />
        </classes>
    </test>
    
    <test name="Chrome">
        <parameter name="browser" value="chrome"></parameter>
        <classes>
            <class
                name="com.oneapi.ta.oneapihub.runners.OneApiHubTestAutomationRunnerTest" />
        </classes>
    </test>
    
<!--    <test name="Edge"> -->
<!--        <parameter name="browser" value="edge"></parameter> -->
<!--        <classes> -->
<!--            <class -->
<!--                name="com.oneapi.ta.oneapihub.runners.OneApiHubTestAutomationRunnerTest" /> -->
<!--        </classes> -->
<!--    </test> -->


<!--    <test name="Safari"> -->
<!--        <parameter name="browser" value="safari"></parameter> -->
<!--        <classes> -->
<!--            <class -->
<!--                name="com.oneapi.ta.oneapihub.runners.OneApiHubTestAutomationRunnerTest" /> -->
<!--        </classes> -->
<!--    </test> -->
</suite> 
 

Это мой runnerClass

 @BeforeClass(alwaysRun = true)
    public void setUpClass() throws Exception {
    
        testNGCucumberRunner = new TestNGCucumberRunner(this.getClass());
    }

    @Parameters({ "browser" })
    @BeforeMethod
    public static void launchBrowser(String browser) throws Throwable {
        DriverManager.testNgBrowserParameter = browser;
    }

    @Test(dataProvider = "scenarios")
    public void runScenario(PickleWrapper pickleWrapper, FeatureWrapper featureWrapper, ITestContext iTestContext)
            throws Throwable {
        
        String browser = iTestContext.getCurrentXmlTest().getLocalParameters().get("browser");

        System.out.println("Running Test on Browser:"   browser   " Thread ID:"   Thread.currentThread().getId());
        if (ExtentReportManager.getFeature(featureWrapper.toString()) == null) {
            ExtentReportManager.startFeature(featureWrapper.toString());
            ExtentReportManager.startScenario(featureWrapper.toString(), pickleWrapper.getPickle().getName());
            ExtentReportManager.getScenario().assignCategory(browser);

        } else {
            ExtentReportManager.startScenario(featureWrapper.toString(), pickleWrapper.getPickle().getName());
            ExtentReportManager.getScenario().assignCategory(browser);
        }
        DriverManager.setScenarioName(pickleWrapper.getPickle().getName());
        DriverManager.setFeatureName(featureWrapper.toString().replace(""", ""));
        DriverManager.setTagName(pickleWrapper.getPickle().getTags().toString().replaceAll("([^a-zA-Z\s])", ""));
        testNGCucumberRunner.runScenario(pickleWrapper.getPickle());
    }

    @DataProvider(parallel = true)
    public Object[][] scenarios() {
        return testNGCucumberRunner.provideScenarios();
    }

    @AfterMethod
    public static void closeBrowser() {
        DriverManager.stopDriver();
        ExtentReportManager.flushExtentReport();
        DriverManager.removeFinishedMap();
    }

    @AfterClass(alwaysRun = true)
    public void tearDownClass() throws Exception {
        testNGCucumberRunner.finish(); The error is this line.
        //SendEmail.sendTestResaultWithEmail();
    }
 

Это DriverManager

initializeDriver это мой метод создания драйвера.

 private static Map<Integer, WebDriver> webDriverMap = new HashMap<Integer, WebDriver>();
    private static Map<Integer, String> browserMap = new HashMap<Integer, String>();
    private static Map<Integer, String> scenarioNameMap = new HashMap<Integer, String>();
    private static Map<Integer, String> featureNameMap = new HashMap<Integer, String>();
    private static Map<Integer, String> tagNameMap = new HashMap<Integer, String>();
    public static Map<String, String> scenarioSteps = new HashMap<String, String>();
    public String getBrowser () {
        
        return browserMap.get((int)Thread.currentThread().getId());
    }
    public static WebDriver getDriver() {

        return (WebDriver) webDriverMap.get((int)Thread.currentThread().getId());
    }

    public static synchronized void startDriver(String browser, String scenarioName) throws Throwable {
        
        webDriverMap.put((int)Thread.currentThread().getId(), initializeDriver(browser, scenarioName));
    }
    
    public static synchronized void setScenarioName(String scenarioName) throws Throwable {
        
        scenarioNameMap.put((int)Thread.currentThread().getId(), scenarioName);
    }
    
    public static synchronized String getScenarioName() throws Throwable {
        
        return scenarioNameMap.get((int)Thread.currentThread().getId());
    }
    
    public static synchronized void setFeatureName(String featureName) throws Throwable {
        
        featureNameMap.put((int)Thread.currentThread().getId(), featureName);
    }
    
    public static synchronized String getFeatureName() throws Throwable {
        
        return featureNameMap.get((int)Thread.currentThread().getId());
    }
    
    public static synchronized void setTagName(String tagName) throws Throwable {
        
        tagNameMap.put((int)Thread.currentThread().getId(), tagName);
    }
    
    public static synchronized String getTagName() throws Throwable {
        
        return tagNameMap.get((int)Thread.currentThread().getId());
    }
    
    public static synchronized void setScenarioSteps(String scenario, String steps) throws Throwable {

        scenarioSteps.put(scenario, steps);
    }
    
    public static synchronized String getScenarioSteps(String scenario) throws Throwable {
        
        return scenarioSteps.get(scenario);
    }
    
    public static synchronized void removeFinishedMap() {
        
        webDriverMap.remove((int)Thread.currentThread().getId());
        scenarioNameMap.remove((int)Thread.currentThread().getId());
        browserMap.remove((int)Thread.currentThread().getId());
        featureNameMap.remove((int)Thread.currentThread().getId());
        tagNameMap.remove((int)Thread.currentThread().getId());
    }
    
public static void stopDriver() {
         getDriver().quit();
         webDriverMap.remove((int)Thread.currentThread().getId());
    }
 

Комментарии:

1. Возможно, стоит рассмотреть возможность использования вместо карт с идентификатором потока. ThreadLocal

Ответ №1:

 public String getBrowser () {
public static WebDriver getDriver() {
public static void stopDriver() {
 

Эти методы не синхронизированы. Это позволяет одновременно изменять карту webdriver и другие карты.

Вы должны синхронизировать эти методы. Или рассмотрите возможность использования a ThreadLocal вместо map, поскольку вы пытаетесь переопределить ту же семантику.

Комментарии:

1. Привет, @M.P. Korstanje, как я могу тебя подключить к локальной сети? это так? «ThreadLocal<RemoteWebDriver> driver = new ThreadLocal<>();»