Selenium 使用 python 多进程模块 multiprocessing 并发执行测试用例

Jerry li · 2018年09月11日 · 最后由 Jerry li 回复于 2024年07月22日 · 8808 次阅读

前言

在批量执行测试用例时,为了提高执行效率,多进程并发是一个很好的方式。

python 并发执行测试用例的例子

from multiprocessing.dummy import Pool as ThreadPool
import random,time
# 设置并发数量
threadNum = 3

# 修改为从数据库中读取用例列表
def get_case_list():
    return [i for i in range(1,20)]

# 具体的执行方法, 记录测试结果和测试时间
def run_case(case_id):
    run_time = random.randrange(1,10)
    time.sleep(run_time)
    print('run case: %d, result is pass, run time is : %d seconds' %(case_id, run_time))

# 设置多进程执行
pool = ThreadPool(threadNum)
pool.map(run_case, get_case_list())
pool.close()
pool.join()

运行结果:

run case: 1, result is pass, run time is : 6 seconds
run case: 3, result is pass, run time is : 7 seconds
run case: 5, result is pass, run time is : 8 seconds
run case: 6, result is pass, run time is : 1 seconds
run case: 4, result is pass, run time is : 4 seconds
run case: 2, result is pass, run time is : 5 seconds
run case: 7, result is pass, run time is : 6 seconds
run case: 11, result is pass, run time is : 5 seconds
run case: 9, result is pass, run time is : 6 seconds
run case: 10, result is pass, run time is : 2 seconds
run case: 8, result is pass, run time is : 5 seconds
run case: 13, result is pass, run time is : 2 seconds
run case: 12, result is pass, run time is : 9 seconds
run case: 17, result is pass, run time is : 1 seconds
run case: 15, result is pass, run time is : 8 seconds
run case: 14, result is pass, run time is : 8 seconds
run case: 18, result is pass, run time is : 8 seconds
run case: 16, result is pass, run time is : 7 seconds
run case: 19, result is pass, run time is : 8 seconds

Process finished with exit code 0

对应的用例管理

目的:每条用例独立管理

方式一:使用描述性的方式管理用例(即关键字驱动)

例如:Chrome,前往 |http://www.baidu.com,|id@@kw@@selenium,点击 |id@@su,验证 |Web填写 Browser Automation,截图

代表纯粹的执行步骤,实现用例完全脱离代码。具体实现可参考之前的分享: https://testerhome.com/topics/15534

方式二:在代码中通过方法管理用例

例如编写用例如下:

from selenium import webdriver
import time

def search_selenium():
    # 在百度首页输入“selenium”,并验证查询结果中包含“Web Browser Automation”
    driver = webdriver.Chrome()
    driver.get('http://www.baidu.com')
    driver.maximize_window()
    driver.find_element(by='id' ,value='kw').send_keys('selenium')
    driver.find_element(by='id' ,value='su').click()
    time.sleep(2)
    elements = driver.find_elements(by='xpath', value="//*[contains(.,'Web Browser Automation')]")
    assert len(elements)>0
    driver.quit()

需执行该用例时,调用对应方法即可:

# 具体的执行方法修改为:
def run_case(case):
    exec(case)

结合 selenium docker 的并发

目前设置并发数为 6 ,selenium node 的最大并发设置为 10, 可以顺畅地执行。
注: selenium node 的并发比实际使用的并发设置得要大,这是为了预留一些用例执行异常时无法释放资源(即 driver 没有正常退出),导致实际可用的资源不足的情况。

测试未执行的空闲状态:

并发数设置为 6 时的工作状态:

最佳回复

我是根据每个用例的类型,在初始化的时候指定对应的 driver 类型(例如 chrome、Firefox)。每一个用例都发到 selenium Server 上,它会自动分配到对应的节点浏览器。

至于并发,参考我这篇文章的例子,所有用例组成一个数据队列,按指定的进程数量进行并发执行即可。

共收到 25 条回复 时间 点赞

首先你这是多进程吧。其次多进程上限应该是看 CPU 核数的,4 核 CPU 也就是 8 个逻辑核应该同一时间只支持 8 进程吧?还 PYTHON 的多进程多线程不是出了名的烂吗,也只使用与 io 密集型的测试

wzy287522564 回复

多谢指正, 是多进程,我修改过来了。

wzy287522564 回复

效率上我觉得还好吧, 因为数据量不算特别大,6 个并发是挺稳定的

你好,我有个问题想问下,目前多进程并发的话,用例之间有没有影响? 好想知道你这个方案是怎么做的,还是用的是 selenium grid 吗? 我现在想着能不能在同一个机器上面多进程来跑,也不知道有没有影响?

selenium grid 是支持一台服务器上并发多个进程的

https://testerhome.com/topics/15534
可以参考之前分享的实现方式

Jerry li 回复

你好,你指的一台服务器上并发多进程,每个进程执行不同的用例吗? 我想要的就是每个进程执行不同的用例效果

Jerry li 回复

看了你之前写的那个平台,不过还是不太清楚,怎么做到分发不同的测试用例到不同的节点上面去,求大佬指点一二。。呵呵 ~~

我是根据每个用例的类型,在初始化的时候指定对应的 driver 类型(例如 chrome、Firefox)。每一个用例都发到 selenium Server 上,它会自动分配到对应的节点浏览器。

至于并发,参考我这篇文章的例子,所有用例组成一个数据队列,按指定的进程数量进行并发执行即可。

也就是说实际上两个地方在做多进程并发:
1、 用例的并发执行。实现方式就是例子里的 pool.map(run_case, case_id_list)

2、selenium 服务节点上的并发执行,这是 selenium Server 自带的

Jerry li 回复

非常感谢你的回复,回头我有空弄个环境调试下,有问题再请教,谢谢

  1. 上面那个例子 case_id_list 改成 get_caes_list() 会不会好些,不然复制下来,运行不了_^
  2. get_caes_list 中的 ‘caes’ 写错了, 应该是 case

是的,笔误,已经改过来了

一通操作猛如虎😂
if platform.system() == 'Windows':
newHub(IsOpen('127.0.0.1', port0))
else:
print('other system is not supported yet !')

spook 回复

你要在非 Windows 系统启动吗? 可以看一下怎么启动 selenium server 的 jar 包和获取默认端口

案例分享出来只是一种探讨,请大家积极,理性,公平的讨论😇

你好,请问一下 “目前设置并发数为 6 ”,这里的数量是在哪里设置呢

liqi629 回复

Jerry li 回复

感谢 LZ 的回复。
这里你的图为什么有好多个浏览器图标呢。我的只有一个

liqi629 回复

哦,你说的这里 这是你启动 selenium server 的时候有一个参数可以指定的,你可以查一下

例如有 2 个 py 文件

test_a.py

@pytest.mark.smoke
@pytest.mark.usefixtures("browser")
@pytest.mark.usefixtures("case_home")
class TestUserStoryOne():
"""
用例之间有依赖,即 1 成功 才能 2 成功,才能 3 成功
"""

@pytest.mark.parametrize("data", operation_system_1)
def test_1(self, browser, data):
pass

def test_2(self, browser):
pass

def test_3(self, browser):
pass

test_b.py

@pytest.mark.smoke
@pytest.mark.usefixtures("browser")
@pytest.mark.usefixtures("case_home")
class TestUserStoryTwo():
"""
用例之间有依赖,即 1 成功 才能 2 成功,才能 3 成功
"""

@pytest.mark.parametrize("data", operation_system_1)
def test_1(self, browser, data):
pass

def test_2(self, browser):
pass

def test_3(self, browser):
pass

正常的运行方式一般是 pytest.main(["-s", "-v","-m=smoke","--html=" + html_report,"--junit-xml=" + xml_report,])

我想实现。启动 2 个浏览器,分别取运行 test_a.py 和 test_b.py。 而且测试文件中的 case 按照顺序执行。

可以部署到线上 centos 上么

849656290 回复

你指的是哪一部分? 只要环境 OK,Python 什么的都有,操作系统应该没问题的

liqi629 回复

楼主有好的解决方案么

zhangmiaomiao 回复

你是遇到 21 楼一样的问题吗? 最简单的方法就是起两个 pytest 命令分别执行两个文件啊

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册