2. 测试框架选型:Python单元测试框架对比

做自动化测试,选框架是第一步。

说实话,这一步很多人会纠结。Python里最主流的两个单元测试框架,就是unittest和pytest。我当年刚入行时也纠结过,后来踩了不少坑,才慢慢摸清楚它们的脾气。

2.1 unittest vs pytest:一场老将与新秀的较量

先说说unittest。它是Python标准库自带的,不用额外安装。这一点很友好。但用起来嘛……我个人觉得有点啰嗦。

你看,unittest要求你写测试类,还要继承TestCase,方法名必须以test开头。断言也得用self.assertEqual这种写法。代码量不小。

而pytest呢?它更自由。函数名带test就行,断言直接用Python原生的assert。简洁太多了。

我举个例子你就明白了:

# unittest 写法
import unittest

class TestMath(unittest.TestCase):
    def test_add(self):
        self.assertEqual(1 + 1, 2)

# pytest 写法
def test_add():
    assert 1 + 1 == 2

看到了吧?pytest的代码量少了一半。我在项目中带新人时,用pytest他们上手更快,基本看一遍就会写了。

下面这张表,是我总结的核心区别:

对比项 unittest pytest
安装方式 内置,无需安装 需 pip install pytest
用例编写 必须写类,继承TestCase 函数即可,无需类
断言方式 self.assertEqual() 等 原生 assert
fixture机制 setUp/tearDown,较笨重 @pytest.fixture,灵活强大
参数化 需用subTest,较麻烦 @pytest.mark.parametrize,一行搞定
插件生态 几乎没有 非常丰富(allure、xdist等)
报告输出 默认文本,较简陋 可生成HTML、Allure等精美报告

我的建议:新项目直接用pytest。除非你是在维护老项目,或者公司强制要求用unittest,否则别犹豫。

2.2 pytest核心优势:为什么我选它?

pytest的优势,说白了就三个字:省事儿

第一,fixture机制太香了。

unittest里的setUp和tearDown,每个测试类都得写一遍。而且作用域是类级别的,想跨类复用?得自己想办法。

pytest的fixture就不一样了。你可以定义在conftest.py里,全局共享。还能控制作用域:function、class、module、session。想怎么用就怎么用。

我在项目中遇到过这样一个场景:多个测试模块都需要登录操作。用unittest的话,每个类里都得写一遍登录逻辑。用pytest,我只需要在conftest.py里定义一个fixture,所有测试文件都能直接引用。省了多少重复代码啊。

# conftest.py
import pytest

@pytest.fixture(scope="session")
def login_session():
    # 登录操作,只执行一次
    token = do_login("admin", "123456")
    return token

# test_case.py
def test_get_user_info(login_session):
    # 直接使用login_session
    response = get_user_info(login_session)
    assert response.status_code == 200

第二,参数化测试,一行代码搞定。

测试中经常需要测多组数据。unittest的做法是写多个测试方法,或者用subTest。代码又长又丑。

pytest的parametrize装饰器,一行就能搞定多组数据测试。而且失败时能清楚看到是哪组数据出了问题。

import pytest

@pytest.mark.parametrize("input_val, expected", [
    (1, 2),
    (2, 4),
    (3, 6),
    (0, 0),
    (-1, -2),
])
def test_double(input_val, expected):
    assert double(input_val) == expected

第三,插件生态丰富。

pytest有几百个插件。我最常用的几个:

  • pytest-xdist:并行执行测试,速度翻倍
  • pytest-html:生成漂亮的HTML报告
  • pytest-allure-adaptor:集成Allure报告,适合大项目
  • pytest-cov:统计代码覆盖率
  • pytest-rerunfailures:失败用例自动重跑

嗯,这里要注意:插件虽好,但别装太多。装多了启动会变慢,反而影响效率。

2.3 环境搭建:5分钟搞定

环境搭建其实很简单。我一般用虚拟环境,避免污染全局Python。

第一步:创建虚拟环境

python -m venv venv
source venv/bin/activate  # Linux/Mac
venv\Scripts\activate     # Windows

第二步:安装pytest

pip install pytest

第三步:安装常用插件

pip install pytest-html pytest-xdist pytest-cov

第四步:验证安装

pytest --version

看到版本号就说明装好了。

小技巧:你可以把依赖写进requirements.txt,下次直接pip install -r requirements.txt一键安装。

避坑指南:我曾经在Windows上遇到过编码问题。pytest默认用UTF-8,但Windows控制台可能是GBK。如果测试文件里有中文,可能会报错。解决方案是在pytest.ini里加上:

[pytest]
testpaths = tests
python_files = test_*.py
python_functions = test_*

或者在conftest.py里设置编码:

import sys
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

好了,环境搭好了,框架也选好了。下一章我们开始写第一个测试用例。你想想看,从零到一其实就这么简单。