TestProject Forum

Run different browsers at the same time

Hi. I am currently running several test using TP Agent, all running in a single browser window. For this particular case I need two separate browsers to run and interact with each other (one “student-browser” browser would simulate a student taking an exam and the oner one “proctor-browser” would simulate a proctor authorising and supervising the student). The flow implies the student asking for authorisation in student-browser, then the proctor confirming in proctor-browser. This interaction needs to be synced since the proctor needs to wait the student to ask for permission and then the student waits the proctor to grant it. Then the flow includes some other interactions between the two browser windows.
I was able to open a FF browser and a Chrome browser, each of them displaying different pages by using “vanilla” Selenium webdriver, but when I try to do the same with TP webdriver I get:

if BaseDriver.__instance is not None:
    raise SdkException("A driver session already exists")
    src.testproject.sdk.exceptions.sdkexception.SdkException: A driver session already exists

This is my initial sample code for managing more than one browser at a time:

def test_multiple_browsers():
    ff_driver = webdriver.Firefox(token=settings.tp_token)
    ff_driver.report().disable_auto_test_reports(disabled=True)
    ff_driver.report().disable_command_reports(disabled=True)

    driver = webdriver.Chrome(token=settings.tp_token)
    driver.report().disable_auto_test_reports(disabled=True)
    driver.report().disable_command_reports(disabled=True)
    ff_driver.get("http://google.com")
    driver.get("http://yahoo.com")

Did anyone face this before? Any help would be more than appreciated.
Thanks in advance

Hello @federico.giraldi,

Currently using the local agent you can only run one test at a time,
however this can be solved by spinning up multiple docker agents
To run coded tests using TestProject’s Open SDK on docker agents you will have to create yaml file as described in here:

https://hub.docker.com/r/testproject/agent

The Open SDK configuration is at the end of this document.

After you configured your yaml file correctly, you will need to spin the container by using:

docker-compose -f <file_name> up -d

After the container is up, you can run your code and it should execute on the Dockerized agent.
Note that if you configured a port that is different from 8585, you will have to change the: TP_AGENT_URL environment variable in your code.

You can also define multiple docker agents in your yaml file, each agent will be with a different port(each docker agent is a different service essentially), here is an example:

If you want to run your python scripts using Docker agents in an ephemeral way, you can do it by running those tests in a pipeline as described in this document:

Using OpenSDK within CI/CD

Hey @artem.kuznetsov ! Thanks for your quick and detailed reply. Unfortunately this doesn’t solve my problem. What I need is to be able to handle 2 webdriver instances at the same time doing different stuff and synchronize their efforts. I have taken a look to the webdriver class and I see it uses a singleton approach, so it looks this is a dead end. It raises an SdkException (here python-opensdk/basedriver.py at master · testproject-io/python-opensdk · GitHub for reference)
So, to my understanding it looks like there is no way to create more than one instance of a webdriver when testing with the SDK. Is that correct? I don’t need more agents, I just need more than one webdriver

Hi @federico.giraldi

Agent that support parallel execution is coming soon (2-3 weeks),
when it’s out, your scenario can be easily achieved, however until then please try the below:

You will need two Agents indeed that listen on different ports.
But as you noticed, SDK also behaves as a singleton, so you will need two separate processes:

  1. For the student communicating with Agent #1 and browser #1
  2. For the proctor communicating with Agent #2 and browser #2

If your application allows, by inspecting UI periodically, you can sync events such as “permissions requested” or “permissions granted” and take automated actions. Otherwise, an in-memory DB, a queue, or something similar must coordinate the actions of the two drivers running in separate processes.

Here’s the flow in a nutshell:

image

Here are the docker-compose scripts for both swarms:

Agent #1

version: "3.1"
services:
  testproject-agent:
    image: testproject/agent:latest
    container_name: testproject-agent
    depends_on:
      - chrome
    environment:
      TP_SDK_PORT: "25001"            # Agent will listen on port 25001 for SDK connections
      CHROME: "chrome:4444"           # Address for Agent to communicate with Chrome browser
      CHROME_EXT: "localhost:5551"    # Address for accessing the Chrome Selenium server
    ports:
    - "25001:25001"                    # Expose port for SDK<->Agent communication
  chrome:
    image: selenium/standalone-chrome
    shm_size: '1gb'
    ports:
    - "5551:4444"                     # Expose Selenium on port 5551

Agent #2

version: "3.1"
services:
  testproject-agent:
    image: testproject/agent:latest
    container_name: testproject-agent
    depends_on:
      - chrome
    environment:
      TP_SDK_PORT: "25002"            # Agent will listen on port 25002 for SDK connections
      CHROME: "chrome:4444"           # Address for Agent to communicate with Chrome browser
      CHROME_EXT: "localhost:5552"    # Address for accessing the Chrome Selenium server
    ports:
    - "25002:25002"                    # Expose port for SDK<->Agent communication
  chrome:
    image: selenium/standalone-chrome
    shm_size: '1gb'
    ports:
    - "5552:4444"                     # Expose Selenium on port 5552

Driver #1 will connect through port 25001 and driver #2 will connect through port 25002, e.g.

Test #1

driver = new ChromeDriver(new URL("http://localhost:25001"), new ChromeOptions());
driver.findElement(By.id("request-permissions-button")).click();

Test #2

driver = new ChromeDriver(new URL("http://localhost:25002"), new ChromeOptions());
while(!driver.findElement(By.id("grant-permissions-button")).isDisplayed()) {
    TimeUnit.SECONDS.sleep(1);
}
driver.findElement(By.id("grant-permissions-button")).click();

You can also use the TP_AGENT_URL environment variable in your tests to specify the Agent address. Refer to Agent Remote Connectivity for more information regarding how to connect to different Agents.

Hi @marat ! Thanks for such a detailed answer. We are currently analizing your in-detail solution in order to check if we can be able to implement something like this. I really appreciate your dedication and I thank you a lot for your time on this topic. Will come back to this once we decide what approach to go for.
Thanks man!

@federico.giraldi
You are more than welcome.
Don’t hesitate to ask if you need any assistance with this setup.

Also, stay tuned for our parallel execution release where this setup will be built-in.