Skip to main content

How to Test Two Users at Once

Intro​

Some features need more than one user: a chat, a shared document, a game, or an approval where one user asks and another one answers. A test with one browser can only check one side. What matters is that what one user does shows up for the other user.

A Solution​

Give each user a browser profile of their own, in the same test. Each profile has its own cookies and storage, so for the site they are two different users. The test drives them one step at a time: one user sends something, and the test waits until the other user sees it.

  • Selenium creates a user context for each user, with WebDriver BiDi. A user context is a fresh browser profile inside the same browser, so one browser is enough, and it starts much faster than a second one. The test opens a window in each user context. WebDriver commands act on the current window, so the test switches to the window of a user before their steps.
  • Playwright and Vibium do the same with browser contexts: newContext() creates one, and each page of the test belongs to one context.
  • Selenide creates two SelenideDriver objects, each with its own browser. WebdriverIO has multiremote: the configuration names one browser for each user, and the test gets each one with multiRemoteBrowser.getInstance().

User contexts need a browser with WebDriver BiDi (Chrome, Edge or Firefox). With other browsers, start one driver for each user, like the Selenide example does.

The users don't wait for each other. When a user sends a message, the other user gets it a moment later, so the test waits for it instead of reading the page right away. The same goes for the start: a user only gets the messages sent after they joined, so the test waits until the other user is in before it sends anything.

Example​

The examples use the chat page of the-internet. Everyone in the same room sees the messages of the others, over a WebSocket. The page shows the connection in #status ("Connected"), the user joins with a name (#name and #join) and sends with #message and #send. The #messages list shows each message as "Alice: Hi Bob", and a notice when someone joins ("Bob joined").

Each run uses a random room (/chat?room=<name>): tests running at the same time, for example on other machines, don't see each other's messages.

Alice and Bob open the chat and join the room. Alice waits until Bob is in, and says "Hi Bob". Bob waits for it, and answers "Hi Alice", which Alice waits for.

Expected Behavior​

  • A browser starts with a profile for Alice and one for Bob (user contexts or browser contexts; Selenide and WebdriverIO start two browsers)
  • Both open the chat in the same random room, wait until it's connected, and join
  • Alice waits until Bob joined, and sends "Hi Bob"
  • Bob sees the message, and answers "Hi Alice"
  • Alice sees the answer
  • The browser closes

Summary​

A browser profile for each user lets a test check what one user does from the side of the other user. Keep each user's steps in small functions (join, send a message), wait for what the other user should see, and keep the users apart from other test runs (here, with a random room).

Happy Testing!

Authors​

Diego Molina
Elemental Selenium maintainer