为 profanity-check 脏话检测库编写自动化测试:pytest 实战与 CI 集成完整指南
【免费下载链接】profanity-checkA fast, robust Python library to check for offensive language in strings.项目地址: https://gitcode.com/gh_mirrors/pr/profanity-check
profanity-check 是一个基于机器学习(线性 SVM)的 Python 脏话检测库,只需predict()和predict_prob()两个接口,就能快速完成敏感词与攻击性语言判断。今天这篇文章,我们将以 pytest 为主角,手把手带新手为 profanity-check 编写自动化测试,并把它接入 CI 持续集成流程,打造一套可回归、可信赖的脏话检测测试体系。
为什么脏话检测库更需要自动化测试
很多新手会问:一个「判断脏话」的库,为什么还要写测试?原因其实很关键:
- 模型行为无法肉眼穷举:profanity-check 没有硬编码黑名单,而是靠 20 万条人工标注样本训练出的模型做语义判断,输入变化多端,人工抽查根本覆盖不完。
- 回归风险高:模型重训、scikit-learn 或 joblib 升级、样本集调整,都可能让同一句话的结果「悄悄漂移」。
- 性能与准确率需要持续守护:官方基准测试中,单条预测仅约 0.2ms,测试准确率高达 95%,这些核心指标必须靠自动化测试长期盯住。
简单说:测试就是脏话检测库的「安全网」,谁都不想上线后发现predict()突然失灵。
环境准备:5 分钟快速配置 pytest 测试环境
开始之前,先准备好运行环境。假设你已经克隆了仓库:
git clone https://gitcode.com/gh_mirrors/pr/profanity-check cd profanity-check pip install -r requirements.txt pip install pytest pytest-covrequirements.txt中已经声明了scikit-learn与joblib两个核心依赖,模型文件则存放在profanity_check/data/目录下(model.joblib和vectorizer.joblib),安装后即可直接调用。
读懂项目现有测试代码 tests/test_profanity_check.py
好消息是:这个开源项目已经内置了测试文件,位于tests/test_profanity_check.py,里面有test_accuracy和test_edge_cases两个用例,虽然用的是原生assert而非 pytest 特性,但已经展示了核心思路:
def test_accuracy(): texts = [ 'Hello there, how are you', 'fuck you', 'GO TO hElL, you dirty scum', ] assert list(predict(texts)) == [0, 1, 1]它验证了三类关键场景:普通文本返回 0(干净)、脏话返回 1(涉脏)、大小写混合依然能被识别。源码中predict()与predict_prob()定义在profanity_check/profanity_check.py,通过profanity_check/__init__.py对外导出,测试时直接from profanity_check import predict即可。
从零编写第一个 pytest 用例:敏感词检测冒烟测试
在tests/下新建test_basic.py,写一个最基础的冒烟测试:
import pytest from profanity_check import predict, predict_prob def test_clean_text(): assert predict(['今天天气真不错'])[0] == 0 def test_profane_text(): assert predict(['fuck you'])[0] == 1 def test_prob_range(): probs = predict_prob(['clean', 'fuck you']) assert 0 <= probs[0] <= 1 assert 0 <= probs[1] <= 1跑一下pytest tests/,看到绿色通过,你的第一个 pytest 用例就完成了。注意predict()返回的是 numpy 数组,所以取单条结果要加[0]。
边界情况与脏话变体测试:提升测试覆盖率
高质量的测试不能只测「教科书样本」,要主动攻击边界。参考原项目test_edge_cases的思路,继续补充:
def test_edge_cases(): # 空字符串、纯空格 assert list(predict(['', ' '])) == [0, 0] # 超长重复文本,确保性能不崩 assert predict(['aaaaaaa' * 100])[0] == 0 def test_known_weakness(): # 已知弱点:数字变体拼写可能漏判,先记录现状,模型改进后更新断言 print('f4ck you ->', predict(['f4ck you'])[0])把「已知弱点」写进测试是个非常好的习惯:当未来模型重训后,这条用例会自动提醒你「弱点是否已被修复」,形成持续改进的闭环。
pytest 参数化:让测试用例更简洁高效
与其复制粘贴一堆相似断言,不如用@pytest.mark.parametrize参数化,一条用例覆盖多种输入:
@pytest.mark.parametrize("text,expected", [ ("hello world", 0), ("fuck you", 1), ("fUcK u", 1), ("go to hell, you scum", 1), ("this is a normal sentence", 0), ]) def test_predict_param(text, expected): assert predict([text])[0] == expected跑一遍pytest -v,你能清楚看到每一条参数组合的通过情况,排查失败时一目了然。
CI 集成实战:GitHub Actions 自动跑测试
测试写好了,接下来让它「自动化」——每次提交代码、发起合并请求时自动运行,这就是 CI(持续集成)。虽然项目 README 早期用的是 Travis CI,今天我们以更主流的 GitHub Actions 为例,在仓库根目录创建.github/workflows/ci.yml:
name: CI on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.11" - run: pip install -r requirements.txt pytest pytest-cov - run: pytest tests/ --cov=profanity_check --cov-fail-under=80关键点有两个:
- 多版本矩阵:把
python-version改成["3.9", "3.11"]列表,即可同时在多个 Python 版本上跑测试,防止「在我电脑上能跑」的尴尬。 - 覆盖率门槛:
--cov-fail-under=80表示覆盖率低于 80% 时构建直接失败,倒逼测试质量。
之后每次 push,GitHub Actions 都会自动拉取代码、安装依赖并执行全部测试,任何回归都会第一时间在 PR 页面亮起红灯。
自动化测试最佳实践清单
最后,把这次实战的要点总结成清单,方便你直接照做:
- 边界优先:空串、纯空格、超长文本、大小写混写都要覆盖。
- 把弱点写进测试:如
f4ck you这类数字变体,先记录现状再持续跟踪。 - 断言概率行为:
predict_prob()的输出应始终在 0~1 之间。 - 参数化去重:同类输入用
parametrize,测试代码更易维护。 - 固定依赖版本:锁住 scikit-learn、joblib 版本,避免升级导致结果漂移。
- 设置覆盖率门槛:在 CI 中强制
--cov-fail-under,守住质量底线。 - 回归即报警:任何模型或依赖变更,都要确保全量测试自动触发。
从读懂tests/test_profanity_check.py,到用 pytest 参数化、边界用例,再到 GitHub Actions 自动集成,一条完整的脏话检测测试链路就搭建完成了。照着这份指南动手实践一遍,你的 profanity-check 项目将从此拥有「自动守护」,任何一次改动都会在几分钟内得到可信的反馈。🚀
【免费下载链接】profanity-checkA fast, robust Python library to check for offensive language in strings.项目地址: https://gitcode.com/gh_mirrors/pr/profanity-check
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考