把本地windows10
中的中文字体 (C:\Windows\Fonts
) 随便选择几种拷贝到服务器的路径(/usr/local/selenium_grid/fonts
)
查看字体
/usr/local/selenium_grid/fonts
[root@VM-24-13-centos fonts]# ll
总用量 65268
-rw-r--r-- 1 root root 16829116 3月 24 18:15 msyhbd.ttc
-rw-r--r-- 1 root root 12139380 3月 24 18:15 msyhl.ttc
-rw-r--r-- 1 root root 19647736 3月 24 18:14 msyh.ttc
-rw-r--r-- 1 root root 18214472 3月 24 18:15 simsun.ttc
docker-compose
pip3 install docker-compose
compose.yml
chrome:
image: selenium/node-chrome:3.8.1
links:
- hub:hub # 这里是把挂载到hub下面的意思
ports:
- "5902:5900" # 给vnc调试用
environment:
- NODE_MAX_INSTANCES=5 # 实例化和下面参数一般保持一致,可以多机并行
- NODE_MAX_SESSION=5
- SCREEN_WIDTH=1920
- SCREEN_HEIGHT=1080
volumes:
- /dev/shm:/dev/shm # 挂载这个持久化数据,据说是为了防止不同的闪退
- ./fonts:/usr/share/fonts # 把中文字体挂载进来,解决截图乱码问题
hub:
image: selenium/hub:3.8.1
ports:
- "7777:4444" # 7777为外部web访问端口
-d
表示后台执行docker-compose up -d
http://ip:7777/grid/console/?config=true&configDebug=true
pip3 install selenium
import time
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from multiprocessing import Process
print(11111)
# ip = "远程ip"
ip = "localhost"
driver = webdriver.Remote(
command_executor="http://%s:7777/wd/hub" %ip,
desired_capabilities=DesiredCapabilities.CHROME
)
print(22222)
def test(i):
time.sleep(3)
driver.get("https://www.baidu.com")
print(driver.title, i)
if __name__ == '__main__':
test(1)
driver.close()
driver.quit()
环境搭建
window10
安装好python3
pytest
pytest-html
生成测试报告插件pytest-xdist 分布式用例
pip install pytest
pip install pytest-xdist
pip install pytest-html
pytest
源代码文件,解决报告乱码问题D:\app\Python37\Lib\site-packages\pytest_html\plugin.py
class TestResult:
def __init__(self, outcome, report, logfile, config):
#self.test_id = report.nodeid.encode("utf-8").decode("unicode_escape")
self.test_id = re.sub(r'(\\u[a-zA-Z0-9]{4})',lambda x:x.group(1).encode("utf-8").decode("unicode-escape"),report.nodeid)
testcase
是用例目录,里面分为了大回归、小回归、冒烟文件夹,用例放不同的用例testcase
目录下由conftest.py
这里面对pytest
和pytest-html
可以进行有些设置# conftest.py
import pytest
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from py._xmlgen import html
_driver = None
# @pytest.fixture()
@pytest.fixture(scope='session', autouse=True)
def driver():
global _driver
print(11111)
ip = "远程ip"
server = "http://%s:7777/wd/hub" % ip
# ip = "localhost"
_driver = webdriver.Remote(
command_executor="http://%s:7777/wd/hub" % ip,
desired_capabilities=DesiredCapabilities.CHROME
)
# 返回数据
yield _driver
# 实现用例后置
_driver.close()
_driver.quit()
@user3per
def pytest_runtest_makereport(item):
"""
当测试失败的时候,自动截图,展示到html报告中
:param item:
"""
if not _driver:
return
pytest_html = item.config.pluginmanager.getplugin('html')
outcome = yield
report = outcome.get_result()
report.description = str(item.function.__doc__)
extra = getattr(report, 'extra', [])
if report.when == 'call' or report.when == "setup":
xfail = hasattr(report, 'wasxfail')
if (report.skipped and xfail) or (report.failed and not xfail):
screen_img = _capture_screenshot()
if screen_img:
html = '<div><img src="data:image/png;base64,%s" alt="screenshot" style="width:1024px;height:768px;" ' \
'onclick="window.open(this.src)" align="right"/></div>' % screen_img
extra.append(pytest_html.extras.html(html))
report.extra = extra
def pytest_html_results_table_header(cells):
cells.insert(1, html.th('用例名称'))
cells.insert(2, html.th('Test_nodeid'))
cells.pop(2)
def pytest_html_results_table_row(report, cells):
cells.insert(1, html.td(report.description))
cells.insert(2, html.td(report.nodeid))
cells.pop(2)
def pytest_html_results_table_html(report, data):
if report.passed:
del data[:]
data.append(html.div('通过的用例未捕获日志输出.', class_='empty log'))
def pytest_html_report_title(report):
report.title = "pytest示例项目测试报告"
def _capture_screenshot():
"""
截图保存为base64
:return:
"""
return _driver.get_screenshot_as_base64()
# test_selenium.py
mport os
import time
import pytest
class TestCase(object):
@pytest.mark.finished
def test_001(self, driver):
time.sleep(3)
driver.get("https://www.baidu.com")
print(driver.title)
driver.find_element_by_id("kw").click()
driver.find_element_by_id("kw").send_keys("你好")
def test1_001(self, driver):
time.sleep(3)
driver.get("https://www.baidu.com")
print(driver.title)
driver.find_element_by_id("kw").click()
driver.find_element_by_id("kw").send_keys("你好")
# runner.py
import os
from multiprocessing import Process
import pytest
def main(path):
# 这里的-n 3 意思就是同时并发3个用例执行
pytest.main(['%s' %path,'-n 3', '--html=report.html','--self-contained-html', '--capture=sys'])
if __name__ == '__main__':
test_case = Process(target=main, args=("d:\\project\\py_selenium_grid\\testcase\\大回归\\",))
test_case.start()
test_case.join()
...
直接用pytest 命令执行
...
pytest-xdist
经过测试,在云服务器(双核)上跑,可以正常跑,如果指定进程太大,会造成容器内存泄漏,服务器出现长期卡死,所以建议:每次执行任务时,都把容器删了重建,同时进程不要指定太大
docker
容器中排除内存情况:docker exec -it ec3d30bff042 top
,其中ec3d30bff042
是selenium/node-chrome
的镜像pytest-parallel
这个无论是在服务器还是本地 win 上跑,都报错pytest-multithreading
发现个问题
pytest-html
上的记录日志,会被打乱,因此如果要使用的化,建议在conftest.py
中,记录日志的代码去掉pip install pytest-multithreading -i https://pypi.douban.com/simple
pytest -s testcase/大回归/小回归/冒烟 --th 10 --html=report.html --self-contained-html --capture=sys
我在【TesterHome 系列征文活动 | 自动化测试实践】等你,一起 day day up!