Search code examples
javaseleniumparallel-processinggridtestng

Selenium Parallel Tests Queue Handling


I have a dynamic list that contains 5k to 10k searching keywords. The keywords received by api that i built, Once I receive a request I launching 5 to 50 browsers parallel (selenium drivers). All the devices needs to run this list in a website in a round robin or any good way seprate the list between each browser. The browsers need to will run without repeating the keywords again.Can anyone assist me please? I am stuck on it for a long time Thanks

Edit: This Method starts the total browsers in parallel (The browsers are already up its just reusing)

    public void testNGBrowser() {
    TestNG tng = new TestNG();
    tng.setPreserveOrder(true);
    tng.setVerbose(1);

    XmlSuite suite = new XmlSuite();
    suite.setName("Keywork-Search");
    suite.setParallel(XmlSuite.ParallelMode.TESTS);
    suite.setThreadCount(DRIVERS.size());
    suite.setVerbose(DRIVERS.size());

    for (int i = 0; i < DRIVERS.size(); i++) {
        XmlTest test = new XmlTest(suite);
        List<XmlClass> classes = new ArrayList<>();
        test.setName("KEYWORD" + i);
        test.setGroupByInstances(true);

        classes.add(new XmlClass(SMS.class));
        test.setXmlClasses(classes);
    }
    List<XmlSuite> suites = new ArrayList<>();
    suites.add(suite);

    tng.setParallel(XmlSuite.ParallelMode.TESTS);
    tng.setXmlSuites(suites);
    tng.run();
}

This Test are used for all the parallel devices

 @Test
    public void VerifyKeyword() {
 System.out.println("VerifyKeyword method, ThreadID: " + 
 Thread.currentThread().getId());
        try {
            Thread.sleep((long) (Math.random() * 10000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        WebDriver driver = getWebDriver();
        VerifyPage verifyPage = new VerifyPage(driver);
        try {
            for (int i = 0; i < KEYWORDS.size(); i++){
                keyword= KEYWORDS.get(KEYWORDS.size() - 1);
                KEYWORDS.remove(keyword);
                verifyPage.verifyKeyword(keyword);
             }
          }
       }

I trying always to take the last keyword and then delete the keyword that already run but there is sometimes conflicts that 2 browsers using same keyword


Solution

  • Try to add a class thread specified for your task, and separate the keywords list to keywords chunks for each thread:

    @Test
    public void verifyKeywordTest() {
    
    // Beginning of code here
    
    List<String> keywordsChunks = getChuncks(KEYWORDS);
    keywordsChunks.forEach(chunk -> {
        VerifyKeyword verifyKeyword = new VerifyKeyword(getWebDriver(), LOCK, chunk);
        verifyKeyword.start();
    
    // Rest of the code here
    

    Runnable class:

    class VerifyKeyword implements Runnable {
    
        WebDriver driver;
        VerifyPage verifyPage;
        private Thread thread;
        private List<String> keywords;
        private final Object LOCK;
        private volatile boolean exit = false;
    
    
        public VerifyKeyword(
                WebDriver driver, Logger logger, Object LOCK, List<String> keywords) {
            this.driver = driver;
            this.keywords = keywords;
            this.LOCK = LOCK;
        }
    
        @Override
        public void run() {
    
            VerifyPage verifyPage = new VerifyPage(driver);
            try {
                for (int i = 0; i < keywords.size(); i++){
                    keyword = keywords.get(keywords.size() - 1);
                    keywords.remove(keyword);
                    verifyPage.verifyKeyword(keyword);
                 }
              }     
            synchronized (LOCK) {
                LOCK.notify();
            }
        }
    
        public void start() {
            if (thread == null) {
                thread = new Thread(this, this.getClass().getName());
                thread.start();
            }
        }
    
        public void stop() {
            exit = true;
        }
    }