1

I built an automation framewoek using maven, java, testng, selenium. As for now I am running my tests sequential and I would like to run them in parallel, however each time I try to run them in parallel there are several browsers that opens (like intended to) but I pay attention that only one window get the actions and other one opens (navigate to the url needed, but no action is being done beside it), I am using threads in order to initialize my webdriver and that they won't intefere each other in doing the actions.

This is my BaseTest class where I declare my webdriver and init it:

public class BaseUiTest extends BaseApiTest {
private static final Browser BROWSER = Browser.valueOf(EnvConf.getProperty("ui.browser.type"));
protected DriverWrapper driver;
protected LoginPage loginPage;
protected TopBar topBar;
protected CmsPage cmsPage;

@BeforeClass(alwaysRun = true)
public final void BaseUiSetup(ITestContext context) throws IOException {
    driver = DriverWrapper.open(BROWSER, TEST_OUTPUT_FOLDER);
    DriverFactory.getInstance().setDriver(driver);
    driver = DriverFactory.getInstance().getDriver();
    System.out.println("HEREREREREFSLKFSKJHFKJSHKJFSHKJFSHKJFSHKJFSHKJ");
    loginPage = new LoginPage(driver);
    cmsPage = new CmsPage(driver);
}


@AfterClass(alwaysRun = true)
public final void baseTeardown() {
    Date testEndTime = new Date();
    if (driver != null) {
        printBrowserLog();
        DriverFactory.getInstance().removeDriver();
    }
    Log.i("testEndTime=[%s]", testEndTime);
  }
}

My DriverWrapper class only wrap the traditional WebDriver interface in this manner:

public class DriverWrapper implements WebDriver {

    private final WebDriver driver;
    private final static Logger Log = Logger.getLogger(DriverWrapper.class.getName());
    private static final Duration WAIT_ELEMENT_TIMEOUT = new Duration(EnvConf.getAsInteger("ui.locator.timeout.sec"), TimeUnit.SECONDS);

    private DriverWrapper(WebDriver driver){
        this.driver = driver;
    }

    public static DriverWrapper open(Browser browser, File downloadsFolder) {
        Log.info(String.format("Starting new %s browser driver", browser));
        switch (browser) {
            case FIREFOX:
                return createFireFoxInst();
            case CHROME:
                return createChromeInst(downloadsFolder);
            default:
                throw new IllegalArgumentException("'" + browser + "'no such browser type");
        }
    }

 
    private static DriverWrapper createChromeInst(File downloadsFolder){
        WebDriverManager.chromedriver().setup();

        ChromeOptions options = new ChromeOptions();
        options.setHeadless(EnvConf.getAsBoolean("selenium.headless"));
        options.setAcceptInsecureCerts(true);
        options.addArguments("--lang=" + EnvConf.getProperty("selenium.locale"));

        LoggingPreferences logPrefs = new LoggingPreferences();
        logPrefs.enable(LogType.BROWSER, Level.SEVERE);

        options.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
        options.addArguments("--window-size=" + EnvConf.getProperty("selenium.window_size"));

        ChromeDriverService service = ChromeDriverService.createDefaultService();
        ChromeDriver driver = new ChromeDriver(service, options);
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        //enabling downloading resources when driver is headless
        enableHeadlessDownload(service, driver, downloadsFolder);

        return new DriverWrapper(driver);
    }

    private static void enableHeadlessDownload(ChromeDriverService service, ChromeDriver driver, File downloadsFolder){
        try(CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
            Map<String, Object> commandParams = new HashMap<>();
            commandParams.put("cmd", "Page.setDownloadBehavior");
            Map<String, String> params = new HashMap<>();
            params.put("behavior", "allow");
            params.put("downloadPath", downloadsFolder.getAbsolutePath());
            commandParams.put("params", params);
            ObjectMapper objectMapper = new ObjectMapper();
            String command = objectMapper.writeValueAsString(commandParams);
            String u = service.getUrl().toString() + "/session/" + driver.getSessionId() + "/chromium/send_command";
            HttpPost request = new HttpPost(u);
            request.addHeader("content-type", "application/json");
            request.setEntity(new StringEntity(command));
            CloseableHttpResponse response = httpClient.execute(request);
            Log.info(String.format("enable download, status code=[%d]", response.getCode()));
        }catch (Exception e){
            Log.error("failed to send command=[age.setDownloadBehavior] to chrome server");
            Log.error(e.getMessage());
        }
    }
}

This is my DriverFactory class (where all the magic happens and where I defined my webdriver threads):

public class DriverFactory {

    private DriverFactory() {}

    private static DriverFactory instance = new DriverFactory();

    public static DriverFactory getInstance() {
        return instance;
    }

    ThreadLocal<DriverWrapper> driver = new ThreadLocal<>(); //thread local driver object for webdriver

    public DriverWrapper getDriver() {
        return driver.get();
    }

    public void setDriver(DriverWrapper driverParam){ //call this method to set the driver object
        driver.set(driverParam);
    }

    public void removeDriver(){
        driver.get().quit();
        driver.remove();
    }
}

And this is my testng.xml file:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="Automation_Suite" parallel="tests" thread-count="4">

    <test name="Critical tests to run after DEV deploy build">
        <groups>
            <run>
                <include name="critical"/>
            </run>
        </groups>
        <classes>
            <class name="com.hackeruso.automation.ui.cms.categories.CategoriesTest"/>
        </classes>
    </test>
    <test name="Critical tests to run after DEV deploy build2">
        <groups>
            <run>
                <include name="critical"/>
            </run>
        </groups>
        <classes>
            <class name="com.hackeruso.automation.ui.cms.content_manager.ContentManagerPresentationTest"/>
        </classes>
    </test>
    <test name="Critical tests to run after DEV deploy build3">
        <groups>
            <run>
                <include name="critical"/>
            </run>
        </groups>
        <classes>
            <class name="com.hackeruso.automation.ui.cms.cyberpedia.TermsTest"/>
        </classes>
    </test>
    <test name="Critical tests to run after DEV deploy build4">
        <groups>
            <run>
                <include name="critical"/>
            </run>
        </groups>
        <classes>
            <class name="com.hackeruso.automation.ui.cms.institutions.ClassesTest"/>
        </classes>
    </test>
</suite>

And this is the profiles section in my pom.xml file that defines this profile(critical tests):

 <profiles>
        <profile>
            <id>critical</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>2.20</version>
                        <configuration>
                            <suiteXmlFiles>
                            <suiteXmlFile>critical_tests.xml</suiteXmlFile>
                            </suiteXmlFiles>
                       </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

This is a test class for example:

public class ContentManagerPresentationTest extends BaseUiTest {
    private static final String PREVIEW_IMAGE_PATH = "/automation-tests/src/test/resources/images/lion.png";
    private static final String PPT_FILE_PATH = "/automation-tests/src/test/resources/ppt/Google_Adword_Project.pptx";
    private static final String NOT_EXIST_PRESENTATION_NAME = "Not Exist";
    private ContentManagerPresentationsCMSPage contentManagerPresentationsCMSPage;
    private VideosNPresentationsRow row;


    @BeforeMethod(alwaysRun = true)
    public void setUpMethod(){
        adminSignIn();
        topBar.clickItem(TopNavBarItem.CMS);
        contentManagerPresentationsCMSPage = cmsPage.selectItemSidePanelDropDownMenu(SidePanelDropDownMenuOptions.CONTENT_MANAGER, "presentations");
        Assert.assertTrue(contentManagerPresentationsCMSPage.verifyElement());
    }

    @AfterMethod(alwaysRun = true)
    public void tearDownMethod(){
        cmsPage.clickLogoutButtonAndVerify();
    }

    @Test(priority = 10, dataProvider = "cancelUploadPresentationsProvider", description = "Cancel upload a new presentation")
    public void cancelUploadNewPresentation(String name, String desc, String previewImgPath, String pptFilePath, boolean toCreate) throws FileNotFoundException {
        contentManagerPresentationsCMSPage
                .uploadNewPresentationOrVideo(name, desc, previewImgPath, pptFilePath, toCreate);
        Assert.assertTrue(contentManagerPresentationsCMSPage.verifyElement(), "Expected to be on presentation main page");
        T_Logger.info("cancelling and returning to main presentation page is successful!");
    }

    @DataProvider(name = "cancelUploadPresentationsProvider")
    public Object[][] cancelUploadPresentationsProvider(){
        return new Object[][]{
                {"Automation Test", "Automation Desc",
                        PREVIEW_IMAGE_PATH,
                        PPT_FILE_PATH,
                        false}
        };
    }

    @Test(priority = 20, description = "Negative test for non exist presentation in the table")
    public void verifyNonExistPresentationInTable(){
        row = contentManagerPresentationsCMSPage.findRowByVideoName(NOT_EXIST_PRESENTATION_NAME);
        Assert.assertNull(row);//, String.format("Row should be null, instead we got =[%s]", row.toString()));
        T_Logger.info("Verification of not exist row in the table is successful");
    }

    @Test(priority = 25, dataProvider = "validationFieldsProvider", description = "Verify mandatory field requirements are fulfilled")
    public void verifyMandatoryFieldsPresentation(String name, String desc, String imagePreviewPath,
                                                  String pptFilePath, boolean toCreate, int msgNumber, String expectedMsg) throws FileNotFoundException {
        contentManagerPresentationsCMSPage
                .uploadNewPresentationOrVideo(name, desc,
                        imagePreviewPath,
                        pptFilePath,
                        toCreate);

        Assert.assertEquals(contentManagerPresentationsCMSPage.getActualErrorMsg(msgNumber), expectedMsg,
                String.format("Expected error message=[%s] is not displayed as expected, instead actual message=[%s]",
                        expectedMsg, contentManagerPresentationsCMSPage.getActualErrorMsg(msgNumber)));
        contentManagerPresentationsCMSPage.clickCreateOrCancel(false);
        T_Logger.info("Verification of mandatory fields is successful");
    }

    @DataProvider(name = "validationFieldsProvider")
    public Object[][] validationFieldsProvider(){
        return new Object[][] {
                {"", "Automation Desc", PREVIEW_IMAGE_PATH, PPT_FILE_PATH, true, 1, "Enter Presentation name"},
                {"Automation Test", "Automation Desc", "", PPT_FILE_PATH, true, 2, "Preview Image is required"},
                {"Automation Test", "Automation Desc", PREVIEW_IMAGE_PATH, "", true, 3, "Presentation file is required"}
        };
    }

    @Test(priority = 30, dataProvider = "addNewPresentationsProvider", description = "Add new presentation",groups = {"critical"})
    public void addNewPresentationAndVerify(String name, String desc, String previewImgPath, String pptFilePath, boolean toCreate) throws FileNotFoundException {
        contentManagerPresentationsCMSPage
                .uploadNewPresentationOrVideo(name, desc, previewImgPath, pptFilePath, toCreate);
        row = contentManagerPresentationsCMSPage.findRowByVideoName(name);
        Assert.assertEquals(row.getNameTxt(), name, String.format("Actual name is =[%s] not as expected", row.getNameTxt()));
    }

    @DataProvider(name = "addNewPresentationsProvider")
    public Object[][] addNewPresentationsProvider(){
        return new Object[][]{
                {"Automation Test", "Automation Desc", PREVIEW_IMAGE_PATH, PPT_FILE_PATH, true}
        };
    }

    @Test(priority = 35, dataProvider = "caseSensitiveProvider", description = "Validation existence of presentation - case sensitive")
    public void searchTablePresentationsCaseSensitive(String pptName){
        row = contentManagerPresentationsCMSPage.findRowByVideoName(pptName);
        Assert.assertNotNull(row);
    }

    @DataProvider(name = "caseSensitiveProvider")
    public Object[][] caseSensitiveProvider(){
        return new Object[][] {
                {"Automation Test"},
                {"AUTOMATION TEST"}
        };
    }
}

The problem: when I run mvn test -Pcritical there are 4 chrome browsers which opens but the actions occur only in one browser (although I defined and manage my webdrivers as threads to handle each one in his own thread), what am I missing?

tupac shakur
  • 658
  • 1
  • 12
  • 29

0 Answers0