Python `tox` / `nox`:多环境测试与自动化集成

好的,各位观众老爷们,各位屏幕前的代码英雄们,欢迎来到今天的“Python多环境测试与自动化集成:toxnox 讲座”。今天咱们不讲虚的,直接上干货,保证各位听完之后,腰不酸了,腿不疼了,一口气能部署十个版本的Python项目!

开场白:为啥我们需要多环境测试?

话说啊,咱们写代码,就跟养孩子似的。你精心呵护的代码,在你的电脑上跑得飞起,结果到了客户的机器上,直接给你跪了。为啥?环境不一样呗!

就好比你给孩子买了一堆玩具,结果到了姥姥家,姥姥说:“这玩具太危险了,我给你换成拨浪鼓!” 你的孩子肯定不乐意啊!

所以,为了避免这种悲剧发生,我们需要多环境测试,确保我们的代码在各种环境下都能稳如老狗。

主角登场:toxnox,测试界的双子星

toxnox,这两位都是Python测试界的扛把子,都是用来管理和运行多环境测试的。它们就像一对双胞胎,长得像,功能也差不多,但是性格略有不同。

  • tox:老牌劲旅,配置即王道

    tox 是个老江湖了,它的核心思想是“配置即代码”。你需要写一个 tox.ini 文件,把你的测试环境和测试命令都配置好,然后 tox 就会自动帮你创建虚拟环境,安装依赖,运行测试。

  • nox:后起之秀,Python代码说了算

    nox 比较年轻,它用 Python 代码来配置测试环境。你可以写一个 noxfile.py 文件,用 Python 代码来定义你的测试流程。这种方式更加灵活,也更符合 Python 程序员的习惯。

第一幕:tox 的魅力

咱们先来看看 tox 怎么玩。

  1. 安装 tox

    pip install tox

    这没啥好说的,安装就完事了。

  2. 编写 tox.ini 文件

    这个文件是 tox 的灵魂,所有的配置都在这里面。咱们来一个简单的例子:

    [tox]
    envlist = py37, py38, py39
    
    [testenv]
    deps =
        pytest
        requests
    commands =
        pytest

    这个 tox.ini 文件定义了三个测试环境:py37py38py39。每个环境都会安装 pytestrequests 这两个依赖,然后运行 pytest 命令。

    咱们来解释一下这些配置:

    • envlist:指定要运行的测试环境列表。
    • deps:指定每个环境需要安装的依赖。
    • commands:指定每个环境要运行的命令。

    你还可以添加更多配置,比如指定 Python 版本,设置环境变量等等。

    配置项 描述
    envlist 指定要运行的测试环境列表。 可以使用逗号分隔多个环境,也可以使用通配符,比如 py{37,38,39}
    deps 指定每个环境需要安装的依赖。可以使用 ==>=<= 等运算符来指定版本。
    commands 指定每个环境要运行的命令。 可以使用多行命令,每行一个命令。
    setenv 设置环境变量。 可以设置全局环境变量,也可以设置特定环境的环境变量。
    passenv 允许传递宿主机的环境变量到测试环境。 例如,passenv = HOME, CI* 表示传递 HOME 环境变量和所有以 CI 开头的环境变量。
    skip_install 如果设置为 True,则跳过依赖的安装。 这在你使用 Poetry 或 Pipenv 管理依赖时很有用。
    changedir 指定测试命令运行的目录。 默认情况下,测试命令在项目根目录运行。
    description 为测试环境添加描述。 这可以帮助你更好地理解每个测试环境的目的。
  3. 运行 tox

    tox

    运行这个命令,tox 就会自动创建虚拟环境,安装依赖,运行测试。

    如果只想运行某个特定的环境,可以使用 -e 参数:

    tox -e py38
  4. tox.ini 的高级用法

    tox.ini 文件可以写得很复杂,它可以包含多个 section,每个 section 可以定义不同的配置。比如,你可以定义一个 [testenv:lint] section,用来运行代码检查工具。

    [tox]
    envlist = py37, py38, py39, lint
    
    [testenv]
    deps =
        pytest
        requests
    commands =
        pytest
    
    [testenv:lint]
    deps =
        flake8
    commands =
        flake8 .

    这个 tox.ini 文件定义了一个 lint 环境,用来运行 flake8 代码检查工具。

第二幕:nox 的逆袭

接下来,咱们来看看 nox 怎么玩。

  1. 安装 nox

    pip install nox

    还是那句话,安装就完事了。

  2. 编写 noxfile.py 文件

    这个文件是 nox 的核心,所有的测试流程都用 Python 代码来定义。咱们来一个简单的例子:

    import nox
    
    @nox.session(python=["3.7", "3.8", "3.9"])
    def tests(session):
        session.install("pytest", "requests")
        session.run("pytest")

    这个 noxfile.py 文件定义了一个 tests session,它会在 Python 3.7、3.8 和 3.9 环境下运行。每个环境都会安装 pytestrequests 这两个依赖,然后运行 pytest 命令。

    咱们来解释一下这些代码:

    • @nox.session:这是一个装饰器,用来定义一个 session。
    • python=["3.7", "3.8", "3.9"]:指定 session 要运行的 Python 版本列表。
    • session.install("pytest", "requests"):安装依赖。
    • session.run("pytest"):运行命令。

    nox 的灵活性在于,你可以用 Python 代码来做任何事情,比如:

    • 根据不同的 Python 版本安装不同的依赖。
    • 根据不同的操作系统运行不同的命令。
    • 自定义测试流程。
  3. 运行 nox

    nox

    运行这个命令,nox 就会自动创建虚拟环境,安装依赖,运行测试。

    如果只想运行某个特定的 session,可以使用 -s 参数:

    nox -s tests
  4. noxfile.py 的高级用法

    noxfile.py 文件可以写得很复杂,它可以包含多个 session,每个 session 可以定义不同的测试流程。比如,你可以定义一个 lint session,用来运行代码检查工具。

    import nox
    
    @nox.session(python=["3.7", "3.8", "3.9"])
    def tests(session):
        session.install("pytest", "requests")
        session.run("pytest")
    
    @nox.session
    def lint(session):
        session.install("flake8")
        session.run("flake8", ".")

    这个 noxfile.py 文件定义了一个 lint session,用来运行 flake8 代码检查工具。

第三幕:toxnox 的爱恨情仇

toxnox 都是好工具,但是它们也有各自的优缺点。

特性 tox nox
配置方式 tox.ini 文件,配置即代码 noxfile.py 文件,Python 代码
灵活性 相对较低 较高,可以用 Python 代码做任何事情
学习曲线 简单,容易上手 稍高,需要熟悉 Python 代码
适用场景 简单的多环境测试,配置变化不大 复杂的测试流程,需要根据不同的环境做不同的处理
可扩展性 可以通过插件扩展,但相对有限 可以用 Python 代码扩展,非常灵活
与 CI 集成 广泛支持,很多 CI 工具都原生支持 tox 需要自己编写脚本来调用 nox,但也很容易
依赖管理 依赖于 pip,可以指定依赖版本 依赖于 pip,也可以结合 PoetryPipenv 使用,更加灵活
社区支持 活跃,文档完善 活跃,文档完善

总的来说,如果你只需要简单的多环境测试,tox 是一个不错的选择。如果你需要更灵活的测试流程,或者你需要根据不同的环境做不同的处理,nox 可能会更适合你。

第四幕:实战演练

光说不练假把式,咱们来一个实战演练。

假设咱们有一个简单的 Python 项目,它的目录结构如下:

myproject/
├── mymodule/
│   ├── __init__.py
│   └── myfunction.py
├── tests/
│   ├── __init__.py
│   └── test_myfunction.py
├── pyproject.toml  # 使用 Poetry 管理依赖
└── README.md

mymodule/myfunction.py 包含一个简单的函数:

def add(a, b):
    return a + b

tests/test_myfunction.py 包含一个简单的测试:

from mymodule.myfunction import add

def test_add():
    assert add(1, 2) == 3

咱们使用 Poetry 来管理依赖,pyproject.toml 文件的内容如下:

[tool.poetry]
name = "myproject"
version = "0.1.0"
description = ""
authors = ["Your Name <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.7"

[tool.poetry.dev-dependencies]
pytest = "^6.0"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

接下来,咱们分别用 toxnox 来配置多环境测试。

  1. 使用 tox

    创建一个 tox.ini 文件:

    [tox]
    envlist = py37, py38, py39
    
    [testenv]
    deps =
        pytest
        # 如果你使用 Poetry,可以注释掉上面的 deps,使用下面这行
        # {[testenv]deps}
    commands =
        pytest

    如果你使用 Poetry 管理依赖,需要注释掉 deps 配置,并添加 {[testenv]deps}。这样 tox 就会使用 Poetry 安装依赖。

    运行 tox 命令,就可以看到测试结果了。

  2. 使用 nox

    创建一个 noxfile.py 文件:

    import nox
    
    @nox.session(python=["3.7", "3.8", "3.9"])
    def tests(session):
        # 如果你使用 Poetry,可以使用下面这行来安装依赖
        session.run("poetry", "install", external=True)
        session.install("pytest")  # 如果不使用 poetry,就用这个
        session.run("pytest")

    如果你使用 Poetry 管理依赖,可以使用 session.run("poetry", "install", external=True) 来安装依赖。external=True 表示运行外部命令。

    运行 nox 命令,就可以看到测试结果了。

第五幕:与 CI 集成

多环境测试的最终目的是为了自动化集成。咱们可以将 toxnox 集成到 CI 工具中,比如 GitHub Actions、GitLab CI 等。

以 GitHub Actions 为例,创建一个 .github/workflows/test.yml 文件:

name: Tests

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [3.7, 3.8, 3.9]

    steps:
    - uses: actions/checkout@v2
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v2
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install poetry
        poetry install
    - name: Test with pytest
      run: |
        pytest

这个 GitHub Actions workflow 会在 Python 3.7、3.8 和 3.9 环境下运行测试。

如果你使用 tox,可以将测试命令改为 tox

    - name: Test with tox
      run: |
        tox

如果你使用 nox,可以将测试命令改为 nox

    - name: Test with nox
      run: |
        nox

剧终:总结与展望

今天咱们聊了 toxnox 这两个多环境测试工具,它们可以帮助我们确保代码在各种环境下都能正常运行。

总的来说,tox 简单易用,适合简单的多环境测试。nox 灵活强大,适合复杂的测试流程。你可以根据自己的需求选择合适的工具。

希望今天的讲座对大家有所帮助。记住,代码质量是项目的生命线,多环境测试是保证代码质量的重要手段。

各位观众老爷们,咱们下期再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注