自动化工具 【开源 LiteReport】告别 JDK 依赖 -- 用 LiteReport 为 pytest 项目打造轻量级测试报告

wusuowei · 2026年05月14日 · 58 次阅读

【开源 LiteReport】告别 JDK 依赖 -- 用 LiteReport 为 pytest 项目打造轻量级测试报告
一行命令,一个 HTML 文件,零额外依赖。

写在前面:测试报告的痛
如果你的团队在用 Python + pytest 做自动化测试,大概率遇到过这个问题:测试跑完了,然后呢?

终端里那一屏绿色的 PASSED 固然让人安心,但当你需要把测试结果同步给团队、归档到 CI/CD、或者回溯上周的测试状态时,纯文本输出就显得力不从心了。

于是你可能考虑过 Allure -- 业界最知名的测试报告框架。它确实强大,但用过之后你会发现:

必须装 JDK。Python 项目要跑报告,先装个 Java 运行时?不少团队在这一步就劝退了。
安装链路长。allure-pytest 只负责采集数据,生成报告还需要单独安装 Allure CLI(通过 npm、brew 或手动下载)。
报告不能直接打开。allure generate 生成的是一个多文件目录,必须 allure open 启动 HTTP 服务才能查看。
CI/CD 集成额外成本。Jenkins 需要装 Allure 插件,GitLab CI 需要额外配置 artifacts 目录。
对于中小团队或个人项目来说,这些"重量"往往不值得。我们需要的不是一个"报告平台",而是一个"报告工具" -- 轻量、快速、开箱即用。

LiteReport:轻量到什么程度?
项目地址:https://pypi.org/project/litereport/

git 地址:https://github.com/moduwusuowei/litereport

LiteReport 是一个专为 pytest 生态设计的轻量级测试报告工具。它的核心理念用一句话概括:

零 JDK、单 HTML 文件、离线可用。

安装:

pip install pytest litereport[pytest]
具体来说:

pip install 即装即用 -- 纯 Python 实现,不依赖 Java、Node.js 或任何外部二进制
pytest --litereport 一键生成 -- 作为 pytest 插件,加一个参数就能自动生成报告
单个 HTML 文件 -- 报告是一个完全自包含的 HTML,双击浏览器打开即可
明暗主题切换 -- 支持 Light / Dark 两种主题,运行时一键切换,自动记忆偏好
中英双语 -- lang: "zh" 或 lang: "en",国际化团队友好
历史追踪 -- 自动保存每次运行快照,在报告中可浏览历史记录
Allure vs LiteReport:一张表说清楚
维度 Allure LiteReport
运行依赖 JDK 8+ (版权问题) Python 3.8+
安装方式 pip + allure CLI (npm/brew) pip install litereport
pytest 集成 allure-pytest + allure generate 两步 pytest --litereport 一步
报告查看 需 allure open 启动 HTTP 服务 双击 HTML 文件
报告体积 多文件目录(JS/CSS/JSON/HTML) 单个 HTML 文件
离线使用 部分功能需 CDN 资源 完全自包含,断网可用
CI/CD 产物 需 Allure 插件或额外配置 直接归档一个 HTML 文件
上手成本 高(JDK + CLI + 插件配置) 低(一个 pip 命令)
这不是说 Allure 不好 -- 它在大型企业级项目中有不可替代的优势(如与 TestOps 集成、自定义 step 等)。但如果你的需求是"跑完测试看个报告",LiteReport 是更务实的选择。

版权问题:

JDK 11 之后会带来版权问题,部分公司可能不会去采购,这是开发该工具的一个主要因素。

真实项目一瞥:API 接口测试
先看一个真实案例。我们有一个基金监控系统,后端用 FastAPI 构建,提供 12 个 API 端点(健康检查、基金列表、技术指标、预警记录、大盘行情、投资分析等)。围绕这些接口,我们用 pytest + LiteReport 搭建了自动化测试,项目结构如下:

api-test/
├── conftest.py # 共享 fixture
├── pytest.ini # pytest 配置
├── litereport.yaml # LiteReport 配置
├── requirements.txt # 依赖: requests, pytest
├── gen_report.py # 独立报告生成脚本
└── tests/
├── test_health.py # 健康检查(3 条用例)
├── test_funds.py # 基金接口(13 条用例)
├── test_indicators.py # 技术指标(7 条用例)
├── test_alerts.py # 预警记录(7 条用例)
├── test_market.py # 大盘行情(7 条用例)
├── test_analysis.py # 投资分析(7 条用例)
└── test_report.py # 持仓报告(5 条用例)
核心是 conftest.py 中的 fixture 设计 -- 用 session 级别的 api_session 保持连接复用,并在测试开始前自动校验 API 可达性:

@pytest.fixture(scope="session")
def api_session(base_url):
"""Shared requests Session with connectivity check."""
s = requests.Session()
try:
resp = s.get(f"{base_url}/health", timeout=5)
assert resp.status_code == 200
except Exception as e:
pytest.exit(f"API 服务不可达: {base_url} ({e})")
yield s
s.close()
一条典型的测试用例长这样:

class TestHealth:
def test_health_check(self, api_session, base_url):
"""健康检查接口应返回 200"""
resp = api_session.get(f"{base_url}/health")
assert resp.status_code == 200
运行非常简单:

pytest --litereport -v
========= 49 passed in 3.42s =========
报告已生成: reports/report.html
49 条测试用例全部通过,一个漂亮的 HTML 报告自动出现在 reports/ 目录下。这就是 LiteReport 在真实项目中的使用体验 -- 你不需要改变任何测试代码,只需要在 pytest 命令后加上 --litereport。

当然,上面这个 API 测试项目需要实际运行的后端服务,你无法直接复现。接下来我们用一个更简单的例子,让你在 5 分钟内亲自体验 LiteReport。

测试生成页面
主页面:

Suits 概览

失败用例:

耗时:

全部用例:

5 分钟上手:数学计算器测试
Step 1:创建项目
mkdir calculator-test && cd calculator-test
python -m venv venv

Windows

venv\Scripts\activate

macOS / Linux

source venv/bin/activate

pip install pytest litereport[pytest]
Step 2:被测代码
创建 calculator.py:

"""简单的数学计算器模块"""


def add(a, b):
"""加法"""
return a + b


def subtract(a, b):
"""减法"""
return a - b


def multiply(a, b):
"""乘法"""
return a * b


def divide(a, b):
"""除法"""
if b == 0:
raise ValueError("除数不能为零")
return a / b
Step 3:编写测试
项目结构目标:

calculator-test/
├── calculator.py # 被测模块
├── litereport.yaml # LiteReport 配置(可选)
└── tests/
├── conftest.py # 共享 fixture
├── test_add.py # 加法测试套件
├── test_subtract.py # 减法测试套件
├── test_multiply.py # 乘法测试套件
└── test_divide.py # 除法测试套件
注意这里的组织方式:每个文件对应一个测试套件(test suite),在 LiteReport 的报告中会按套件维度展示结果分布。

关于 test_suite 的组织原则
在写测试之前,先聊聊 test suite 怎么规划:

按功能模块拆分文件 -- 每个 test_xxx.py 文件就是一个 suite。LiteReport 自动识别文件名作为套件名,所以文件拆分直接影响报告的可读性。

用 class 对场景分组 -- 同一个功能的不同测试场景用 class 归类,比如 TestDivideBasic 和 TestDivideEdgeCases。

命名规范:

文件名:test_<模块>.py
类名:Test<功能><场景>
方法名:test_<具体行为>
testcase 书写规范
好的测试用例应该覆盖这几个维度:

维度 说明 示例
docstring 用中文写清楚"这条用例验证什么",LiteReport 会提取并展示在报告中 """整数除法"""
正向测试 正常输入,验证正确输出 assert add(1, 2) == 3
边界测试 零、负数、大数、浮点数等边界值 assert add(0, 0) == 0
异常测试 非法输入应抛出预期异常 pytest.raises(ValueError)
参数化 多组数据复用同一逻辑,减少重复代码 @pytest.mark.parametrize(...)
下面是完整的测试代码。

tests/conftest.py -- 共享 fixture:

"""共享 fixture"""
import sys
import os

将项目根目录加入 sys.path,确保能 import calculator

sys.path.insert(0, os.path.join(os.path.dirname(file), ".."))
tests/test_add.py -- 加法测试套件:

"""加法运算测试套件"""
import pytest
from calculator import add


class TestAddBasic:
"""基础加法测试"""

def test_add_positive(self):
"""两个正整数相加"""
assert add(1, 2) == 3

def test_add_negative(self):
"""两个负数相加"""
assert add(-1, -2) == -3

def test_add_mixed(self):
"""正数加负数"""
assert add(5, -3) == 2


class TestAddEdgeCases:
"""加法边界测试"""

def test_add_zero(self):
"""加零"""
assert add(5, 0) == 5

def test_add_float(self):
"""浮点数相加"""
assert add(0.1, 0.2) == pytest.approx(0.3)

@pytest.mark.parametrize("a,b,expected", [
(100, 200, 300),
(-100, 100, 0),
(999999, 1, 1000000),
])
def test_add_parametrize(self, a, b, expected):
"""参数化测试:多组数据验证"""
assert add(a, b) == expected
tests/test_subtract.py -- 减法测试套件:

"""减法运算测试套件"""
import pytest
from calculator import subtract


class TestSubtract:
"""减法测试"""

def test_subtract_positive(self):
"""正整数相减"""
assert subtract(5, 3) == 2

def test_subtract_result_negative(self):
"""结果为负数"""
assert subtract(3, 5) == -2

def test_subtract_zero(self):
"""减零"""
assert subtract(5, 0) == 5

def test_subtract_self(self):
"""自身相减等于零"""
assert subtract(42, 42) == 0

@pytest.mark.parametrize("a,b,expected", [
(100, 50, 50),
(-10, -3, -7),
(0, 0, 0),
])
def test_subtract_parametrize(self, a, b, expected):
"""参数化测试"""
assert subtract(a, b) == expected
tests/test_multiply.py -- 乘法测试套件:

"""乘法运算测试套件"""
import pytest
from calculator import multiply


class TestMultiply:
"""乘法测试"""

def test_multiply_positive(self):
"""正整数相乘"""
assert multiply(3, 4) == 12

def test_multiply_negative(self):
"""负数相乘"""
assert multiply(-3, -4) == 12

def test_multiply_mixed_sign(self):
"""正负相乘"""
assert multiply(3, -4) == -12

def test_multiply_by_zero(self):
"""乘以零"""
assert multiply(100, 0) == 0

def test_multiply_by_one(self):
"""乘以一"""
assert multiply(42, 1) == 42

@pytest.mark.parametrize("a,b,expected", [
(0.5, 4, 2.0),
(10, 10, 100),
(-1, -1, 1),
])
def test_multiply_parametrize(self, a, b, expected):
"""参数化测试"""
assert multiply(a, b) == expected
tests/test_divide.py -- 除法测试套件(重点展示异常测试):

"""除法运算测试套件"""
import pytest
from calculator import divide


class TestDivideBasic:
"""基础除法测试"""

def test_divide_integers(self):
"""整数除法"""
assert divide(10, 2) == 5.0

def test_divide_float_result(self):
"""结果为浮点数"""
assert divide(7, 2) == 3.5

def test_divide_negative(self):
"""负数除法"""
assert divide(-10, 2) == -5.0


class TestDivideEdgeCases:
"""除法边界与异常测试"""

def test_divide_by_zero(self):
"""除数为零应抛出 ValueError"""
with pytest.raises(ValueError, match="除数不能为零"):
divide(10, 0)

def test_divide_zero_numerator(self):
"""被除数为零"""
assert divide(0, 5) == 0.0

def test_divide_by_one(self):
"""除以一"""
assert divide(42, 1) == 42.0

@pytest.mark.parametrize("a,b,expected", [
(100, 3, 33.333333),
(1, 7, 0.142857),
(22, 7, 3.142857),
])
def test_divide_precision(self, a, b, expected):
"""浮点精度验证"""
assert divide(a, b) == pytest.approx(expected, rel=1e-4)
Step 4:添加 LiteReport 配置(可选)
创建 litereport.yaml:

report:
title: "Calculator 测试报告"
theme: "light"
lang: "zh"

history:
enabled: true
max_entries: 30

output:
dir: "./reports"
filename: "report.html"

environment:
project: "calculator-test"
test_type: "单元测试"
不创建配置文件也能运行,全部使用内置默认值。配置文件的作用是自定义报告标题、主题、语言等。

Step 5:运行并生成报告
pytest --litereport -v
终端输出类似:

tests/test_add.py::TestAddBasic::test_add_positive PASSED
tests/test_add.py::TestAddBasic::test_add_negative PASSED
tests/test_add.py::TestAddBasic::test_add_mixed PASSED
tests/test_add.py::TestAddEdgeCases::test_add_zero PASSED
tests/test_add.py::TestAddEdgeCases::test_add_float PASSED
tests/test_add.py::TestAddEdgeCases::test_add_parametrize[100-200-300] PASSED
tests/test_add.py::TestAddEdgeCases::test_add_parametrize[-100-100-0] PASSED
tests/test_add.py::TestAddEdgeCases::test_add_parametrize[999999-1-1000000] PASSED
...
tests/test_divide.py::TestDivideEdgeCases::test_divide_by_zero PASSED
tests/test_divide.py::TestDivideEdgeCases::test_divide_precision[100-3-33.333333] PASSED
...
========= 30 passed in 0.15s =========
打开 reports/report.html,你会看到一个完整的测试报告。

报告里有什么?
生成的报告不是简单的文本罗列,而是一个功能完整的单页应用:

概览仪表盘:页面顶部展示整体统计 -- 总用例数、通过数、失败数、跳过数,以及一个环形图直观展示结果分布(每个状态都有对应数字标注)。

套件维度分析:水平堆叠柱状图,按测试文件(suite)维度展示每个文件的通过/失败/跳过分布。在我们的例子中,你会看到 test_add、test_subtract、test_multiply、test_divide 四个套件各自的执行状况。

最慢用例排行:水平条形图展示耗时 Top N 的测试用例,帮助快速定位性能瓶颈。

详情展开:点击任意套件行,展开查看该套件下每条用例的执行结果、耗时、docstring 描述。这也是为什么前面强调 docstring 要写好 -- 它会直接出现在报告中。

搜索与过滤:支持全文搜索测试名称,快速定位特定用例。

明暗主题切换:报告右上角的主题开关,支持 Light / Dark 两种模式,切换后自动记忆偏好。

环境信息:报告底部展示 litereport.yaml 中配置的 environment 字段,如项目名、测试类型等。

进阶用法
配置优先级
LiteReport 的配置有四个层级,优先级从高到低:

CLI 参数 > litereport.yaml (项目) > ~/.litereport/config.yaml (全局) > 内置默认值
比如你想临时改标题,不用修改配置文件:

pytest --litereport --litereport-title="Nightly Build Report"
历史报告追踪
在 litereport.yaml 中开启历史功能:

history:
enabled: true
max_entries: 30
开启后,每次运行 pytest --litereport 都会在 reports/history/ 目录保存一份快照。打开报告后,可以在界面中浏览历史记录,对比不同时间点的测试状态。

独立脚本生成报告
在 CI/CD 场景中,你可能希望"先跑测试,再生成报告"分两步执行。LiteReport 支持这种模式:

from litereport import ReportData, ReportGenerator, LiteReportConfig

加载 pytest --litereport 产出的 JSON 数据

config = LiteReportConfig.load("litereport.yaml")
with open("reports/report_data.json", "r", encoding="utf-8") as f:
data = ReportData.from_json(f.read())

生成报告

gen = ReportGenerator(config)
gen.generate(data, "reports/report.html")
pytest --litereport 运行后除了生成 HTML 报告,还会保存一份 report_data.json 原始数据。你可以基于这份数据用 Python API 重新生成报告,或者做二次处理。

不只是 pytest
虽然 --litereport 插件是最便捷的方式,但 LiteReport 也支持从其他数据源生成报告:

从 JUnit XML 生成(兼容 Jenkins、GitLab CI 等产出格式)

litereport generate junit-results.xml

从 LiteReport JSON 格式生成

litereport generate report_data.json

初始化配置文件

litereport init
什么场景适合用 LiteReport?
中小团队 -- 不想为测试报告引入 JDK 和复杂配置链路
Python 项目 -- 你的项目已经在用 pytest,加一个参数就够了
CI/CD 流水线 -- 需要直接归档单个 HTML 文件作为构建产物
离线环境 -- 报告完全自包含,不依赖外部 CDN 或 HTTP 服务
快速原型 -- 新项目刚起步,先跑通测试报告再说
开始使用
pip install litereport[pytest]
pytest --litereport
两行命令,打开 reports/report.html,你的第一份 LiteReport 测试报告就生成了。

LiteReport 是开源项目,欢迎贡献代码和反馈意见。

期待您的 star~~~

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册