单元测试质量检查器
v1.0.0评估测试套件以满足严格的单元测试标准,分类测试类型,并在假对象(fake objects)和模拟对象(mock objects)之间进行选择。每当开发人员问“是否…”时使用。
运行时依赖
安装命令
点击复制技能文档
单元测试质量检查器 评估现有测试是否符合Feathers标准的真实单元测试,根据类型对每个测试进行分类,评估测试双精选,并生成带有优先改进计划的评分质量报告。 何时使用 使用此技能时: 测试套件运行缓慢,您需要了解原因 您正在审计遗留代码库的测试覆盖质量 团队正在辩论他们的“单元测试”是否真正是单元测试 有人问“这里应该使用模拟还是伪造?” 测试不稳定,难以在本地运行,或者需要环境设置才能运行 不要使用此技能来从头写新的测试。 对于写入特征测试,请使用特征测试写入。 对于打破依赖以使测试更快,请使用依赖打破技术执行器。 背景和输入收集 在开始之前,请确认: 测试文件路径或目录 - 测试文件存放在哪里?(test/,src/test/,spec/等) 语言和测试框架 - JUnit,pytest,NUnit,RSpec,Vitest,Go测试等 测试是否可以运行? - 是否可以使用Bash运行整个套件或单个文件并测量时间? 是否存在已知的测试双精选? - 代码库中是否存在任何现有的伪造,模拟,存根或间谍? 如果用户无法运行测试,则时间分析将是静态的(基于模式)。 在报告中明确标记此事。 过程 步骤1:清点测试 使用Glob和Grep枚举测试文件并计算单个测试用例。 Glob:test/*/.{java,py,ts,js,rb,cs,go}(适应语言) Grep:测试方法/函数声明的模式 记录:总测试数,检测到的测试框架,测试文件结构。 原因:您无法对无法看到的测试进行分类。 计数还表明测试套件是否处于一种规模,使得缓慢的测试会导致构建延迟几分钟。 步骤2:应用四个排除标准 对于每个测试文件,使用Grep查找模式以表明不符合单元测试标准。 四个排除标准 - 测试不是单元测试如果: 与数据库交谈 跨网络进行通信 触摸文件系统 需要特殊环境设置才能运行(编辑配置文件,设置环境变量,启动服务) Grep模式(适应语言): 排除标准 数据库 DataSource,EntityManager,@Repository,sqlite3,psycopg2,mongoose,ActiveRecord,db.execute,cursor.execute 网络 HttpClient,requests.get,fetch(,RestTemplate,socket.,urllib,axios,WebClient 文件系统 File(,open(,fs.readFile,FileInputStream,Path.of,os.path,tmpfile,shutil 环境设置 System.getenv,os.environ,process.env,dotenv,application.properties在测试级别加载,@SpringBootTest,@IntegrationTest 对于每个标记的测试,请记录: 文件,测试名称,排除类型,行引用。 原因:这四个排除标准是具体的和可检查的。 一个测试可以在逻辑上很小,同时仍然违反所有四个排除标准。 排除标准是Feathers定义与非正式的“小测试”含义之间存在差异的原因 - 排除标准存在是因为DB/网络/FS/环境依赖使测试变慢,易于出错,无法将故障局限于特定范围。 步骤3:测量时间 如果Bash访问可用,请运行测试套件(或代表性子集)并测量每个测试的时间。 JUnit / Maven mvn test -pl module 2>&1 | grep "Tests run" pytest带时间 pytest --tb=no -q --durations=20 Jest npx jest --verbose --testPathPattern="..." Go go test ./... -v -timeout 60s 2>&1 | grep -E "^--- (PASS|FAIL)" 阈值:任何单个测试超过1/10秒(100ms)都是缓慢的单元测试。 这是一个定义,而不是一个指南。 一个需要1/10秒才能运行的测试就是一个缓慢的单元测试。 标记每个超过100ms的测试。 对于总时间超过60秒的套件,标记最慢的前10个测试作为优先目标。 原因:速度不是一种很好的质量 - 它是定义性的。 一个缓慢的测试套件停止为开发人员提供快速的反馈。 当测试需要几分钟时,开发人员停止运行它们。 整个反馈循环被打破。 步骤4:对每个测试进行分类 使用排除结果和时间数据,将每个测试分类为以下三种类别之一: 单元测试:通过所有四个排除标准并在100ms内运行。 故障点指向特定的小范围代码。 更高级别的测试:故意涵盖多个类或组件之间的交互。 可能会跨越边界(DB,网络,FS)以设计。 较慢。 有用,用于确定集成行为时单元测试难以编写。 这些是合法的 - 不要要求它们满足单元测试标准。 它们服务于不同的目的。 特征测试:编写用于记录实际当前行为,而不是证明正确性。 通常在遗留代码库中作为安全网,在重构之前。 关键标记:断言与代码当前的行为(可能包括错误)相匹配,而不是应该做什么。 目的:保持行为稳定,同时附近的代码发生变化。 合法类别 - 不要将其重新分类为错误。 边缘/不明确:无法明确分类的测试。