pytest-pyppeteer

pytest-pyppeteer是我写的一个 pytest 插件,支持在 pytest 中运行pyppeteer,起因是为了解决工作中的一个测试需求,现在将其开源并做简单介绍。

背景

为什么不用 selenium?

最根本的原因是 selenium 的配置比较繁琐,最常见的问题是需要保持 webdriver 和浏览器版本的一致性。

pyppeteer 的简单介绍

pyppeteer 是 puppeteer的非官方 python 版本,几乎实现了和其相同的 API,可以非常方便的去操作 Chrome 浏览器。

pyppeteer 的局限性

目前最明显的问题是没有提供跨浏览器的解决方案,最新的 puppeteer 已经提供对 Firefox 的支持,但是 pyppeteer 可能还需要一些时间。

安装

推荐使用pipenv管理虚拟环境,并替换为国内 pip 源。

$ pipenv install pytest-pyppeteer

仅支持 python >= 3.7

快速开始

用下面这个测试用例来说明:断言电影《活着》的豆瓣评分大于 9.0。

from dataclasses import dataclass

from pytest_pyppeteer.models import Browser

@dataclass(init=False)
class Elements:
"""收集所有使用到的页面元素,可以为 XPath 或者 CSS Selector。""" # 查询输入框
query = "#inp-query" # 点击搜索
apply = ".inp-btn > input:nth-child(1)" # 第一条结果
first_result = (
"#root > div > div > div > div > div:nth-child(1) > div.item-root a.cover-link"
) # 评分
rating = (
"#interest_sectl > div.rating_wrap.clearbox > div.rating_self.clearfix > strong"
) async def test_lifetimes(pyppeteer: Browser):
page = await pyppeteer.new_page()
await page.goto('https://movie.douban.com/') await page.type(Elements.query, "活着")
await page.click(Elements.apply) await page.waitfor(Elements.first_result)
await page.click(Elements.first_result) await page.waitfor(Elements.rating)
rating = await page.get_value(Elements.rating) assert float(rating) >= 9.0

执行测试用例,看一下效果:

这里我们无需指定浏览器的路径,pytest-pyppeteer 会在对应平台默认的安装路径下搜寻 Chrome 的可执行文件。

也可以通过 --executable-path命令行选项显示的指定 Chrome 的路径。

或者,在你的conftest.py文件中指定:

@pytest.fixture(scope="session")
def executable_path(executable_path):
if executable_path is None:
return "path/to/Chrome/or/Chromium"
return executable_path

其它支持的命令行选项,包括:

  • --headless:使用浏览器的无头模式;

  • --args:为浏览器指定其它参数。例如:指定代理服务器:

    $ pytest --args proxy-server "localhost:5555,direct://" --args proxy-bypass-list "192.0.0.1/8;10.0.0.1/8"
  • --window-size:指定浏览器的大小,默认是 800*600;--window-size 0 0表示最大化浏览器;

同时操作多个浏览器

用下面这个测试用例来说明:断言书籍《活着》的豆瓣评分高于其电影的评分。

import asyncio
from dataclasses import dataclass from pytest_pyppeteer.models import Browser, Page @dataclass(init=False)
class Elements:
"""公共对象库""" query = "#inp-query"
apply = ".inp-btn > input:nth-child(1)" @dataclass(init=False)
class BookElements(Elements):
url = "https://book.douban.com/" first_result = '(//*[@class="item-root"]/a)[1]'
rating = "#interest_sectl > div > div.rating_self.clearfix > strong" @dataclass(init=False)
class MovieElements(Elements):
url = "https://movie.douban.com/" first_result = (
"#root > div > div > div > div > div:nth-child(1) > div.item-root a.cover-link"
)
rating = (
"#interest_sectl > div.rating_wrap.clearbox > div.rating_self.clearfix > strong"
) async def query_rating(pyppeteer: Browser, name: str, elements: Elements):
"""获取电影或者书籍的评分。""" page: Page = await pyppeteer.new_page() await page.goto(elements.url) await page.type(elements.query, name)
await page.click(elements.apply) await page.waitfor(elements.first_result)
await page.click(elements.first_result) await page.waitfor(elements.rating)
rating = await page.get_value(elements.rating) return rating async def test_multiple_pyppeteer(pyppeteer_factory):
pyppeteer1 = await pyppeteer_factory()
pyppeteer2 = await pyppeteer_factory() movie_rating, book_rating = await asyncio.gather(
query_rating(pyppeteer1, "活着", MovieElements),
query_rating(pyppeteer2, "活着", BookElements)
) assert book_rating >= movie_rating

通过pyppeteer_factory 可以获取多个浏览器实例,再利用 python 标准库asyncio可以很方便的执行异步操作,节省时间。

执行测试用例,看一下效果:

Github 仓库

更多功能可以访问:https://github.com/luizyao/pytest-pyppeteer,如果能帮助到你的话,可以给个 star,也欢迎提 issue 和 pr。

pytest 中文文档(v6.1.1)

之前翻译过 pytest v5.1.3 的官方文档并开源,目前计划更新到 v6.1.1 版本。

项目更多进度可以访问:https://github.com/luizyao/pytest-chinese-doc/tree/6.1.1

pytest-pyppeteer:在pytest中运行pyppeteer的更多相关文章

  1. 不能在Python Console中运行pytest

    在Python Console中运行pytest发现报错了 这是为什么?因为Python Console已经是进入python之后的环境,就像在python自带的IDLE中运行pytest pytes ...

  2. pycharm运行Pytest,有没有将Pytest写入Python代码中的区别

    初学pytest. 将pytest写进Python代码中 不同运行方式都可正常运行     =======================**********************========= ...

  3. pytest——pycharm中右击运行(run)没有问题,在terminal中运行pytest报错:E ModuleNotFoundError: No module named

    参考了这个解决办法:https://blog.csdn.net/qq_36829091/article/details/82180866 我的是Windows,linux的和Windows的解决办法有 ...

  4. pytest(3):pytest运行参数介绍

    前言 pytest 带有很多参数,可以使用 pytest --help  来查看帮助文档,下面介绍几种常用的参数: 无参数 读取路径下所有符合规则的文件,类,方法,函数全部执行.使用方法如下:  py ...

  5. 【pytest系列】- pytest测试框架介绍与运行

    如果想从头学起pytest,可以去看看这个系列的文章! https://www.cnblogs.com/miki-peng/category/1960108.html 前言​ ​ 目前有两种纯测试的测 ...

  6. pytest文档2-用例运行规则

    用例设计原则 文件名以test_*.py文件和*_test.py 以test_开头的函数 以Test开头的类 以test_开头的方法 所有的包pakege必须要有__init__.py文件 help帮 ...

  7. pytest系列(四)- pytest+allure+jenkins - 持续集成平台生成allure报告

    pytest是什么 pytest是python的一款测试框架,拥有unittest的功能并比它更丰富. allure是什么 有非常多的优秀的测试框架,但却是有非常少优秀的报告工具可以展示非常清楚的用例 ...

  8. Pytest单元测试框架-Pytest环境安装

    unittest是python自带的单元测试框架,它封装好了一些校验返回的结果方法和一些用例执行前的初始化操作,使得单元测试易于开展,因为它的易用性,很多同学也拿它来做功能测试和接口测试,只需简单开发 ...

  9. Pytest单元测试框架——Pytest+Allure+Jenkins的应用

    一.简介 pytest+allure+jenkins进行接口测试.生成测试报告.结合jenkins进行集成. pytest是python的一种单元测试框架,与python自带的unittest测试框架 ...

随机推荐

  1. Spring Boot学习(四)常用注解

    一.注解对照表 注解 使用位置 作用  @Controller  类名上方  声明此类是一个SpringMVC Controller 对象,处理http请求  @RequestMapping  类或方 ...

  2. Urule开源版系列5——RuleSetParser解析过程

    接上期Urule开源版系列4--Core包核心接口之规则解析过程 之前源码到了Parser,这期详细解析下RuleSetParser的解析过程 1.主流程 特殊处理一个属性 循环处理元素 当元素名称是 ...

  3. tf.app.flags与argparse功能类似

    https://blog.csdn.net/ei1990/article/details/76423277 tensorflow中tf.app.flags与argparse模块有点类似,通过它们都可以 ...

  4. sql 注入初探

    Sql注入:就是将恶意的sql语句插入到用户输入的参数当中并带入数据库中查询并在浏览器返回不该显示的信息 寻找sql注入点: 1.要有参数值的传递(url当中GET型的.注册用户名的页面.登录框.留言 ...

  5. Python-全局解释器锁GIL原理和多线程产生原因与原理-多线程通信机制

    GIL 全局解释器锁,这个锁是个粗粒度的锁,解释器层面上的锁,为了保证线程安全,同一时刻只允许一个线程执行,但这个锁并不能保存线程安全,因为GIL会释放掉的并且切换到另外一个线程上,不会完全占用,依据 ...

  6. Java高级特性1_流库_初体验

    Java高级特性流库_初体验 面对结果编程 在编程里, 有两种编程方式, 一种是面对过程编程, 一种是面对结果编程. 两者区别如下 面向过程编程 面向过程编程需要编程程序让程序依次执行得到自己想要的结 ...

  7. 当安装、卸载件包时,出现依赖问题 error: Failed dependencies解决办法

    error: Failed dependencies:-- 依赖关系非常复杂,当你试图先安装任何一个包时都会出现这样的依赖关系错误,这时候你就应该强制安装了,我认为只要你把服务或软件需要的包都装上,强 ...

  8. C++(VS2015)模板显式特化之template语法深入理解

    首先说下遇到的情况: 这里在vc++6.0上建立了一个自定义模板类,再去覆盖这个类,分别使用部分覆盖,整体覆盖 但在vs2015上去整体覆盖类会报错. 错误如下: 错误原因:个人感觉是新版本的vs更接 ...

  9. Bayer Pattern——RGGB

    原博客地址:https://blog.csdn.net/joe9280/article/details/46952947 参考:https://blog.csdn.net/wgx571859177/a ...

  10. 对于dijkstra最短路算法的复习

    好久没有看图论了,就从最短路算法开始了. dijkstra算法的本质是贪心.只适用于不含负权的图中.因为出现负权的话,贪心会出错. 一般来说,我们用堆(优先队列)来优化,将它O(n2)的复杂度优化为O ...