0

I have created test classes to test specific page templates for my company's websites. For example: I have written a class called ArticleTests which inherits from a BaseTest object, which takes a URL in its constructor. My company owns many sites, and the article page template is essentially the same across all of them.

My goal is to instantiate ArticleTests for an article page template from each site my company owns. I want all the tests in each ArticleTests instance to run on the same thread, on its own WebDriver.

Something like below:

  • ArticlePage("site1.com/someArticleUrl")
  • ArticlePage("site2.com/someArticleUrl")
  • ArticlePage("site3.com/someArticleUrl")

Each bullet above should execute its own tests, on its own WebDriver, on its own thread.

Code

BaseTest:

public abstract class BaseTest implements ITest {
    
    protected ThreadLocal<String> testName = new ThreadLocal<String>();
    
    public WebDriver driver;
    public WebDriverWait wait;
    
    protected String url;
    protected Page page;
    
    
    public void driverSetup() {
        System.out.println("Setting up driver");
        //set driver path..., etc
        driver = new ChromeDriver();
        
        wait = new WebDriverWait(driver, 60); 
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    }
    
    @BeforeMethod
    public void beforeMethod(Method method) {
        System.out.println("Setting test name");
        
        testName.set(method.getName() + "_" + getBrand(url));
        
        if(driver.getCurrentUrl().equals("data:,"))
            driver.get(page.getUrl());
        

    }
 
    public void teardown () {
        driver.quit();
    }
   
        
    /**
     * A helper method for data providers. Takes a list as an argument and returns a 2D Object array.
     * @param list the list to be converted
     * @return the 2D array of list
     */
    protected <T> Object[][] to2DArray(List<T> list) {
        
        Object[][] result = new Object[list.size()][1];
        
        for(int i = 0; i < list.size(); i++) {
            result[i][0] = list.get(i);
        }
        
        return result;
    }
    
    public abstract String getTestName();
    
}

HeaderTests: - Same idea as ArticleTests, except for the header.

public class HeaderTests extends BaseTest {

    @Factory(dataProvider = "urls", dataProviderClass = URLUtils.class)
    public HeaderTests(String url) {
        this.url = url;
    }

    @BeforeClass
    public void beforeClass() {
        super.driverSetup();
        
        System.out.println("Creating header tests with URL " + url);
        System.out.println("On thread " + Thread.currentThread().getId());
        
        page = new Page(driver, wait, url);
        page.goToHome();
    }

    @Test(dataProvider = "header-logo-links")
    public void homeHeaderLogoClickTest(Link link) {
        
        assertTrue(isWorkingLink(link), "Header Logo did not lead to home on URL " + url);
    }

    
    @Test(dataProvider = "header-newsletter-links")
    public void newslettersignupTest(Link link) {

        assertTrue(isWorkingLink(link), "Newsletter sign up link does not work");
    }
    
    @Override
    public String getTestName() {
        return "Header_" + testName.get();
    }
    
    
    //Data Providers
    
    @DataProvider(name = "header-newsletter-links")  
    public Object[][] headerNewsletterLinks(){
        List<Link> headerSignupLinks = HeaderBrandUtils.getHeaderNewsletterSignupLinks(getBrand(url));
        
        return to2DArray(headerSignupLinks);
    }
    
    @DataProvider(name = "header-logo-links")  
    public Object[][] headerLogoLinks(){
        List<Link> headerSignupLinks = HeaderBrandUtils.getHeaderNewsletterSignupLinks(getBrand(url));
        
        return to2DArray(headerSignupLinks);
    }
    
    @AfterClass
    public void after() {
        System.out.println("Closing driver");
        super.teardown();
    }
}

The HeaderBrandUtils class is a class that checks what site the URL is from, and returns the appropriate object. Example: clicking the header logo for site1 will bring you to site1 homepage, whereas clicking the header logo for site2 brings you to site2's homepage.

The Link class is a class that holds the By locator of a link on a page, and the desired URL of the link located by that By.

URLUtils: - Class to retrieve URLs

public class URLUtils {

    @DataProvider(name = "urls")
    public static Object[][] getUrls() {
        
         List<String> testUrls = new LinkedList<String>();
    
        testUrls.add("site1.com/url");
        testUrls.add("site2.com/url");
        //..

        return to2DArray(testUrls);
    }
    
    /**
     * A helper method for data providers. Takes a list as an argument and returns a 2D Object array.
     * @param list the list to be converted
     * @return the 2D array of list
     */
    protected static <T> Object[][] to2DArray(List<T> list) {
        
        Object[][] result = new Object[list.size()][1];
        
        for(int i = 0; i < list.size(); i++) {
            result[i][0] = list.get(i);
        }
        
        return result;
    }
}

testng.xml:

<suite name="Suite" parallel="tests" thread-count="4">

    <test name="Footer tests" parallel="instances" thread-count="2">
        <classes>
            <class name="com.globalAutomation.tests.footerTests.FooterTests"/>
        </classes>
    </test> 
    
    <test name="Header tests" parallel="instances" thread-count="2">
        <classes>
            <class name="com.globalAutomation.tests.headerTests.HeaderTests"/>
        </classes>
    </test> 
</suite> 

Output

When I run this (via mvn test), the output looks like this:

Creating footer tests with URL on thread 13
Creating footer tests with URL on thread 15
Creating header tests with URL on thread 16
Creating header tests with URL on thread 14
Setting test name
Setting test name
Setting test name
Setting test name
...

4 browsers open up and I see the above output.

Once just one test finishes (not test class, just a @Test) in any of the browsers, another driver opens, then another test finishes, and then another browser opens, and so on...

I don't understand why more than 4 browsers are opening when I set thread-count = 4 at the suite level.

My desire is all the tests in each instance of each test class operate in its own browser, in its own thread.

My questions are:

  • Why am I seeing the results I am seeing?
  • How can I modify my code to achieve my desire?
  • How do I limit the total number of browsers that open?
Community
  • 1
  • 1

0 Answers0