The original article is reprinted from Liu Yue’s Technology Blog https://v3u.cn/a_id_195

“There are so many pubs in so many cities in the world, but she walks into my…..” There are so many systems in the world. There are so many browsers in the system. With only one test machine, do we have to queue up and do compatibility tests one by one? Is there a more efficient way? For this reason, we propose a more efficient solution: using Docker+Selenium Grid.

Selenium Grid is a distributed WebUI testing tool that can distribute test processes across multiple servers for parallel execution. There are two main roles in the Selenium Grid architecture: the Hub is the central point control Node, and the Node is the work Node of the Selenium. They are registered to the Hub and operate the browser to execute the automated test cases issued by the Hub.

In other words, a dispatching center is used to install different operating systems on different machines, and then the corresponding browsers to be tested are installed in the systems. However, it is technically difficult to deploy the distributed Selenium Grid cluster in the traditional way. Also, a browser can have only one version installed on the operating system and only one running instance. For example, in order to test for different versions of Chrome, it is necessary to install the specified version of Chrome browser on different physical machines or virtual machines, which takes a lot of time and machine cost to prepare the test environment.

How do you simplify the complexity of Selenium Grid cluster installation? The answer is Docker, yes, Docker, also see Docker. Docker can use container technology to directly deploy multiple nodes on a single server. The process is simple and convenient, just need to write Dockerfile script, which greatly improves the test efficiency. This time, we use Docker+Selenium Grid to implement the compatibility test of multi-system and multi-version browsers.

First, install Docker, please move: Windows 10 system to play with the DockerToolbox and replace the domestic image source (a variety of chars)

Then, pull the Selenium Grid dispatch center image file:

docker pull selenium/hub

Here we test compatibility with two different browsers: Chrome and Firefox

So pull the image files separately:

docker pull selenium/node-chrome  
docker pull selenium/node-firefox

After all three images have been downloaded successfully, enter the command:

docker images

View local image:

liuyue:mytornado liuyue$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE selenium/node-chrome latest 0843e55de3dc 2 Weeks ago 1.04GB Selenium/Hub Latest 705BE32777F0 2 Weeks ago 283MB Selenium/Node - Firefox Latest F794497D8393 2 months ago 956MB

‘docker-compose’ is a basic container composition tool that can be used to quickly coordinate the use of multiple images. For example, ‘docker-compose’ is a configuration file for ‘docker-compose’.

version: "3"  
services:  
  
  hub:  
    image: selenium/hub  
    ports:  
      - "4444:4444"  
  
    environment:  
      GRID_MAX_SESSION: 16  
      GRID_BROWSER_TIMEOUT: 3000  
      GRID_TIMEOUT: 3000  
  
  chrome:  
    image: selenium/node-chrome  
    container_name: chrome  
    depends_on:  
      - hub  
    environment:  
      HUB_PORT_4444_TCP_ADDR: hub  
      HUB_PORT_4444_TCP_PORT: 4444  
      NODE_MAX_SESSION: 4  
      NODE_MAX_INSTANCES: 4  
    volumes:  
      - /dev/shm:/dev/shm  
    ports:  
      - "9001:5900"  
    links:  
      - hub  
  
  firefox:  
    image: selenium/node-firefox  
    container_name: firefox  
    depends_on:  
      - hub  
    environment:  
      HUB_PORT_4444_TCP_ADDR: hub  
      HUB_PORT_4444_TCP_PORT: 4444  
      NODE_MAX_SESSION: 2  
      NODE_MAX_INSTANCES: 2  
    volumes:  
      - /dev/shm:/dev/shm  
    ports:  
      - "9002:5900"  
    links:  
      - hub

The main content of the configuration file is to deploy the Selenium Grid container service hub on port 4444 and make it accessible to the host machine through port mapping. The mirroring is the Selenium/Hub image we just downloaded. Firefox and Google rely on hub services, and NODE\_MAX\_INSTANCES define how many browser instances can be run.

At this point, we execute the command in the directory where docker-compose.yml is located to start the service:

docker-compose -f docker-compose.yml up -d

The -d parameter means to run in the background, although you can choose to run in the foreground.

Browser then visit http://localhost:4444/grid/console, this request is hosting the local IP, but it is through the access port mapping docker container of Selenium Grid dispatching center:

As you can see, the services of both browsers have started normally, running four instances and two instances respectively. At the same time, you can also run the Docker command from the terminal to view the progress:

docker ps

Returns a list of containers:

liuyue:mytornado liuyue$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES adcd4683f39c The selenium/node - firefox "/ opt/bin/entry_poin..." 2 days ago Up 2 days 0.0.0.0:9002->5900/ TCP Firefox 58dfe5825439 Selenium /node-chrome "/opt/bin/entry_poin..." 2 days ago Up 2 days 0.0.0.0:9001->5900/ TCP chrome 97D602944B34 Selenium /hub "/opt/bin/entry_poin..." 2 days ago Up 2 days 0.0.0.0:4444->4444/ TCP myTornado_hub_1

Now that the browser is ready, the next step is easy. Let’s actually test it with the Docker container by writing test.py:

import time from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities # specify host and port driver operation = webdriver. Remote (command_executor = 'http://127.0.0.1:4444/wd/hub', desired_capabilities=DesiredCapabilities.CHROME) driver.get("https://v3u.cn") time.sleep(1) driver.get_screenshot_as_file("v3u.png") driver.close()

Here, use the Chrome browser driver to use Remote mode, access the host local IP, port 4444, after opening the site, screenshot to check if there is any layout error problem.

View the screenshot:

Or try Firefox:

import time from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities # specify host and port driver operation = webdriver. Remote (command_executor = 'http://127.0.0.1:4444/wd/hub', desired_capabilities=DesiredCapabilities.FIREFOX) driver.get("https://v3u.cn") time.sleep(1) driver.get_screenshot_as_file("v3u_frefox.png") driver.close()

Check out the test screenshots under Firefox:

It’s not a big difference, but you can actually see the differences in details, such as fonts and hyperlink colors, that are part of compatibility testing.

Of course, we could have written a little more standard code. After all, we’re doing compatibility testing, and we don’t want to make any mistakes in our testing. Here’s how to refactor the code using Python’s built-in unit testing library, unittest:

`import os import datetime import time import unittest from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities class Example(unittest.TestCase): def setUp(self): The self. The driver = webdriver. Remote (command_executor = 'http://127.0.0.1:4444/wd/hub', desired_capabilities=DesiredCapabilities.CHROME)` `self.driver.get("https://v3u.cn") def test_firefox(self): time.sleep(1) self.driver.get_screenshot_as_file("v3u_chrome.png") def tearDown(self): self.driver.quit() if __name__ == "__main__": unittest.main(verbosity=1)`

Test results:

Liuyue: pickupname liuyue $python3 "/ Users/liuyue/Downloads/ccpt_21_cvm/mouse/pickupname/test. The p y" / Library/Frameworks/Python framework Versions / 3.7 / lib/python3.7 / site - packages/selenium webdriver/remote/remote_connectio n.py:374: ResourceWarning: Unclosed < SocketKind. Socket FD =5, Family =AddressFamily.AF_INET, Type =SocketKind. 63563), raddr=('127.0.0.1', 4444)> return self._request(command_info[0], url, body=data) ResourceWarning: Enable tracemalloc to get the object allocation traceback / Library/Frameworks/Python framework Versions / 3.7 / lib/python3.7 / site - packages/selenium webdriver/remote/remote_connectio n.py:374: ResourceWarning: Unclosed < SocketKind. Socket FD =5, Family =AddressFamily.AF_INET, Type =SocketKind. 63566), raddr=('127.0.0.1', 4444)> return self._request(command_info[0], url, body=data) ResourceWarning: Enable tracemalloc to get the object allocation traceback / Library/Frameworks/Python framework Versions / 3.7 / lib/python3.7 / site - packages/selenium webdriver/remote/remote_connectio n.py:374: ResourceWarning: Unclosed < SocketKind. Socket FD =5, Family =AddressFamily.AF_INET, Type =SocketKind. 63573), raddr=('127.0.0.1', 4444)> return self._request(command_info[0], url, body=data) ResourceWarning: Enable tracemalloc to get the object allocation traceback / Library/Frameworks/Python framework Versions / 3.7 / lib/python3.7 / site - packages/selenium webdriver/remote/remote_connectio n.py:374: ResourceWarning: Unclosed < SocketKind. Socket FD =5, Family =AddressFamily.AF_INET, Type =SocketKind. 63574), raddr=('127.0.0.1', 4444)> return self._request(command_info[0], url, body=data) ResourceWarning: Enable tracemalloc to get the object allocation traceback . -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- Ran 1 test in 5.908 s OK

When you are done, you can use the docker-compose command to stop the container service in one click, which is very convenient:

docker-compose -f docker-compose.yml down

Especially if the number of containers is very large, we don’t need to manually stop the service one by one:

liuyue:mytornado liuyue$ docker-compose -f docker-compose.yml down  
Stopping firefox         ... done  
Stopping chrome          ... done  
Stopping mytornado_hub_1 ... done  
Removing firefox         ... done  
Removing chrome          ... done  
Removing mytornado_hub_1 ... done  
Removing network mytornado_default  
liuyue:mytornado liuyue$

Check the service process again:

liuyue:mytornado liuyue$ docker ps  
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES  
liuyue:mytornado liuyue$

Conclusion: This time, we have introduced the setup, running and stopping of Selenium Grid, a distributed automated Web testing software, without any problems. By using this automated test approach, we can save a lot of time and get the most accurate test results in an efficient manner. If your existing test machine is better configured, you can explore further and open as many browser instances as possible to do massive concurrent compatibility testing.

The original article is reprinted from Liu Yue’s Technology Blog https://v3u.cn/a_id_195