Home > Software engineering >  selenium test cases with Websocket pass individually but fail if run together
selenium test cases with Websocket pass individually but fail if run together

Time:11-30

I have a HTML page for client page, and Java for server functions. Server and client sides are both connected to Port 8800. This is how I connect client with server:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>something</title>
</head>
<body>
<div ><button id="startButton" onclick="start()" style="visibility: hidden;">START</button></div>
<script type="text/javascript">
        var webSocket = new WebSocket("ws://localhost:8800");
        var startButton = document.getElementById("startButton");

        webSocket.onopen = function(event){ wsOpen(event);};
        webSocket.onmessage = function(event){ wsGetMessage(event);};
        webSocket.onclose = function(event){ wsClose(event);};
        webSocket.onerror = function(event){ wsError(event);};
        function start(){
            wsSendMessage("start," player_id);
            startButton.innerText = "STARTED";
            startButton.disabled="true";
        }
        function wsSendMessage(message){
            webSocket.send(message);
        }
    </script>
</body>
</html>

This is what my server look like:

import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.*;
public class Server extends WebSocketServer {
    public Server(int port) {
        super(new InetSocketAddress(port));
    }
    @Override
    public void onStart() {
        System.out.println("Server started!");
        setConnectionLostTimeout(0);
        setConnectionLostTimeout(500);
    }
something else

I used Selenium to test the webpage. This is my basic config:

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;

import io.github.bonigarcia.wdm.WebDriverManager;
import java.nio.file.Path;
import java.nio.file.Paths;
import static org.junit.jupiter.api.Assertions.*;

public class Test {
    WebDriver driver1;

    String path = "path/web.html";
    Path sampleFile;
    Server server;
    JavascriptExecutor js1;

    @BeforeAll
    static void setupClass() {
        WebDriverManager.chromedriver().setup();
    }
    @BeforeEach
    void setup() throws InterruptedException {
        driver1 = new ChromeDriver();

        js1 = (JavascriptExecutor) driver1;

        sampleFile = Paths.get(path);
        server = new Server(8800);
        server.start();
    }
    @AfterEach
    void teardown() throws InterruptedException {
        driver1.quit();
    }

My two test cases are below:

@Test
    void row41() throws InterruptedException {
        driver1.get(sampleFile.toUri().toString());

        driver1.findElement(By.id("startButton")).click();
       
        //some other operations
        assertEquals(2, server.getNextPlayer());
    }
    @Test
    void row42() throws InterruptedException {
        driver1.get(sampleFile.toUri().toString());
        driver1.findElement(By.id("startButton")).click();
        //some other operations

So the problem is, if I run two tests separately, they will all pass but If I run them together, only the first test will pass, the second one fails with
org.openqa.selenium.ElementNotInteractableException: element not interactable
  (Session info: chrome=107.0.5304.121)
at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:200)
    at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:133)
    at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:53)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:184)
    at org.openqa.selenium.remote.service.DriverCommandExecutor.invokeExecute(DriverCommandExecutor.java:167)
    at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:142)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:567)
    at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:251)
    at org.openqa.selenium.remote.RemoteWebElement.click(RemoteWebElement.java:77)
    at project.Test.row42

And from the html page itself point of view, the startButton is not loaded and displayed on the page (But if the page is connected to server, the button will be loaded).

To narrow down the root cause, I made a copy of my HTML page and named it web2.HTML and let it connect to port 8802 (which connects to a new server instance listening on port 8802). I ran web.html on test 1 and web2.html on test 2, they all passed. So I am assuming it's because the port to which the clien and server connect is not fully freed and thus the error occurs?

If run together, ```Server started``` is printed in ```onStart()``` for test 1 but not test 2

CodePudding user response:

The reason is that you're not shutting down your WS server on tearDown. Since your tests are running in the same process, finishing the test does not lead to terminating the service.

Probably it silently fails to start new one since the port is occupied and you're proceeding with the state changed by previous test, not the clear one.

  • Related