跳转到主要内容

Pyodide使用的应用程序的pytest插件

项目描述

pytest-pyodide

PyPI Latest Release GHA codecov

Pyodide使用的应用程序的pytest插件

安装

pytest-pyodide需要Python 3.10+,可以使用以下命令进行安装

pip install pytest-pyodide

您还需要以下运行时之一

  • Chrome和chromedriver
  • Firefox和geckodriver
  • Safari和safaridriver
  • node v18+

Github可重用工作流程

pytest-pyodide还支持通过/.github/workflows/main.yml中的可重用工作流程在GitHub Actions上进行测试。这允许您在不安装所有测试工具的情况下在一系列浏览器/操作系统组合上进行测试,并轻松将其集成到您的CI过程中。

在您的GitHub Actions工作流程中,将其作为单独的工作调用。要传递构建的wheel,请在使用构建步骤时使用上传工件步骤。

这将运行给定浏览器/pyodide版本/操作系统配置的测试。它将在您的repo的根目录中运行pytest,这应该会捕获子文件夹中的任何test_*.py文件。

jobs:
  # Build for pyodide 0.24.1
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - uses: actions/setup-python@v4
      with:
        python-version: 3.11
    - uses: mymindstorm/setup-emsdk@v11
      with:
        version: 3.1.45
    - run: pip install pyodide-build==0.24.1
    - run: pyodide build
    - uses: actions/upload-artifact@v3
      with:
        name: pyodide wheel
        path: dist
  # this is the job which you add to run pyodide-test
  test:
    needs: build
    uses: pyodide/pytest-pyodide/.github/workflows/main.yaml@main
    with:
      build-artifact-name: pyodide wheel
      build-artifact-path: dist
      browser: firefox
      runner: selenium
      pyodide-version: 0.24.1

如果您想在多个浏览器/Pyodide版本等上运行,您可以使用矩阵策略运行上述main.yaml,或者使用testall.yaml。默认情况下,它将在所有浏览器(和node)上测试多个配置。如果您想减少配置,可以像下面那样使用浏览器、运行器、Pyodide版本列表进行过滤。

  test:
    needs: build
    uses: pyodide/pytest-pyodide/.github/workflows/testall.yaml@main
    with:
      build-artifact-name: pyodide wheel
      build-artifact-path: dist
      pyodide-versions: "0.23.4, 0.24.1"
      runners: "selenium, playwright"
      browsers: "firefox, chrome, node"
      os: "ubuntu-latest, macos-latest"

使用方法

  1. 首先,您需要一个兼容版本的Pyodide。您可以从releases下载Pyodide构建工件。

    wget https://github.com/pyodide/pyodide/releases/download/0.24.1/pyodide-build-0.24.1.tar.bz2
    tar xjf pyodide-build-0.24.1.tar.bz2
    mv pyodide dist/
    
  2. 然后,您可以在测试中使用提供的固定值(seleniumselenium_standalone),

    def test_a(selenium):
        selenium.run("assert 1+1 == 2")   # run Python with Pyodide
    

    您可以使用以下方法运行它们

    pytest --dist-dir=./dist/
    

run_in_pyodide

一些测试只是简单地在一个代码块中运行Pyodide,并确保它不会出错。在这种情况下,可以使用pytest_pyodide中的run_in_pyodide装饰器,例如。

from pytest_pyodide import run_in_pyodide
@run_in_pyodide
def test_add(selenium):
    assert 1 + 1 == 2

在这种情况下,函数的主体将自动在Pyodide中运行。装饰器也可以与packages参数一起使用,以在运行测试之前加载包。例如

from pytest_pyodide import run_in_pyodide
@run_in_pyodide(packages = ["regex"])
def test_regex(selenium_standalone):
    import regex
    assert regex.search("o", "foo").end() == 2

您还可以使用@run_in_pyodidepytest.mark.parametrizehypothesis等一起使用。@run_in_pyodide必须是最内层的装饰器。任何在@run_in_pyodide内部的装饰器都不会对测试行为产生影响。

from pytest_pyodide import run_in_pyodide
@pytest.mark.parametrize("x", [1, 2, 3])
@run_in_pyodide(packages = ["regex"])
def test_type_of_int(selenium, x):
    assert type(x) is int

@run_in_pyodide函数的第一个参数必须是浏览器运行器,通常是一个selenium固定值。剩余的参数和@run_in_pyodide函数的返回值必须是可序列化的。这些参数将在主机Python中序列化,并在Pyodide Python中反序列化。返回值将发生相反的操作。在函数体内,第一个selenium参数将是None(它由固定值内部使用)。请注意,这导致接收到的参数是副本。对参数所做的更改不会反映在主机Python中

@run_in_pyodide
def mutate_dict(selenium, x):
    x["a"] = -1
    return x

def test_mutate_dict():
    d = {"a" : 9, "b" : 7}
    assert mutate_dict(d) == { "a" : -1, "b" : 7 }
    # d is unchanged because it was implicitly copied into the Pyodide runtime!
    assert d == {"a" : 9, "b" : 7}

只要固定值的返回值是可序列化的(最常见的是如果它们是None),您就可以使用固定值。作为一个特殊情况,函数将把selenium固定值视为测试中的None

如果您需要返回Pyodide Python对象的持久引用,可以使用特殊的PyodideHandle

@run_in_pyodide
def get_pyodide_handle(selenium):
    from pytest_pyodide.decorator import PyodideHandle
    d = { "a" : 2 }
    return PyodideHandle(d)

@run_in_pyodide
def set_value(selenium, h, key, value):
    h[key] = value

@run_in_pyodide
def get_value(selenium, h, key):
    return h[key]

def test_pyodide_handle(selenium):
    h = get_pyodide_handle(selenium)
    assert get_value(selenium, h, "a") == 2
    set_value(selenium, h, "a", 3)
    assert get_value(selenium, h, "a") == 3

这可以用来为与@run_in_pyodide一起使用的固定值创建固定值。

您可以使用run_in_pyodide作为内层函数

def test_inner_function(selenium):
    @run_in_pyodide
    def inner_function(selenium, x):
        assert x == 6
        return 7
    assert inner_function(selenium_mock, 6) == 7

然而,函数将看不到任何闭包变量

def test_inner_function_closure(selenium):
    x = 6
    @run_in_pyodide
    def inner_function(selenium):
        assert x == 6
        return 7
    # Raises `NameError: 'x' is not defined`
    assert inner_function(selenium_mock) == 7

因此,内层@run_in_pyodide函数的唯一价值是限制函数定义的作用域。如果您需要一个闭包,您将不得不将其包装在第二个函数调用中。

将文件复制到Pyodide

您可以使用copy_files_to_pyodide装饰器将文件复制到pyodide文件系统。这需要两个参数 - 一个(src,destination)对的列表。这些可以是以下任何一种:1)一个文件名,2)一个文件夹名,它被复制到目标路径(如果recurse_directories为True,则包括所有子目录),3)一个glob模式,它将获取与模式匹配的所有文件并将它们复制到目标目录,同时保留文件夹结构。

如果您将install_wheels设置为True,任何.whl文件都将安装在pyodide上。这对于安装您的包很有用。

from pytest_pyodide.decorator import copy_files_to_pyodide

@copy_files_to_pyodide(file_list=[(src,dest)],install_wheels=True,recurse_directories=True)

在Pyodide中运行非Pyodide测试

此插件还支持在浏览器中运行Pyodide的标准pytest测试。因此,如果您有一个现有的代码库并且您想检查您的Pyodide构建是否正常工作,只需像这样运行即可

# Make the emscripten/wasm32  wheel in the dist folder
pyodide build
# the following code
# a) copies the test_path directory and subfolders to a Pyodide instance, and
# b) installs any wheels in the dist subfolder so that this package is available on the Pyodide VM
pytest --run-in-pyodide test_path --runtime <runtime> --dist-dir=<pyodide/dist>

指定浏览器

您可以使用--runtime--rt)命令行选项指定浏览器运行时。

--runtime的可能选项是

  • node(默认)
  • firefox
  • chrome
  • safari
  • host(不运行基于浏览器的测试)
pytest --runtime firefox
pytest --runtime firefox --runtime chrome

# Adding -no-host suffix will disable running host tests
pytest --runtime chrome-no-host

使用Playwright运行测试(可选)

默认情况下,测试将以Selenium运行。可以使用以下方式使用playwright运行测试。

首先安装playwright浏览器

python -m playwright install --with-deps

然后使用--runner参数指定使用playwright运行测试。

pytest --runner playwright

自定义测试标记

pytest-pyodide支持的自定义测试标记

pytest.mark.driver_timeout(timeout):设置WebDriver中的脚本超时。如果测试已知需要很长时间,可以使用此标记延长截止日期。

pytest.mark.xfail_browsers(chrome="why chrome fails"):在特定浏览器中xfail测试。

示例

examples

兼容的Pyodide版本

兼容性表

许可证

pytest-pyodide使用Mozilla Public License Version 2.0

项目详情


下载文件

下载您平台上的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分发

pytest_pyodide-0.58.3.tar.gz (162.3 kB 查看哈希值)

上传时间

构建分发

pytest_pyodide-0.58.3-py3-none-any.whl (49.7 kB 查看哈希值)

上传时间 Python 3

支持者:

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面