每次测试都要花半小时,而我只是改了个错别字…… Jenkins的忽略测试功能简直就是程序员的救星。
在深入讨论如何忽略测试之前,我们先来快速了解一下Jenkins和自动化测试的基本概念。
Jenkins是一个开源的自动化服务器,广泛应用于实现持续集成和持续交付(CI/CD)流程。
它使开发者能够自动构建、集成和测试代码。
想象一下,每次你提交代码到仓库,Jenkins就像个尽职尽责的质检员,自动检查代码质量并运行测试,及时发现错误和bug。
说到自动化测试,它是现代软件开发中不可或缺的一部分。通过自动化测试,团队可以快速验证代码更改是否引入了回归问题。
但问题来了——当测试用例本身出现问题,或者某些测试在某些环境下不适合运行时,我们该怎么办?
这就是忽略测试的用武之地。它允许我们有条件地跳过某些测试,而不是让整个构建失败。
与完全删除测试不同,忽略测试只是一种临时措施,让团队能够在解决问题期间保持持续集成流程的正常运行。
忽略测试听起来像是一种“逃避”问题的方式,但实际上,它在许多场景下都非常有用。以下是五个常见的需要忽略测试的情况:
环境问题:某些测试可能依赖于特定的环境配置,如数据库、网络服务或硬件资源。当这些依赖在特定环境中不可用时,跳过相关测试是合理的选择。
例如,在Jenkins配置分布式测试执行时,可以通过设置“test_slice”变量来跳过不属于当前切片的测试。
测试稳定性问题:有些测试可能是“脆弱”的(flaky test),即它们会随机失败,不是因为代码有问题,而是因为测试本身的设计问题。
如Spark项目中就曾忽略过一个流式查询监听器套件中的flaky测试。
资源密集型测试:某些测试可能需要大量系统资源,如内存或CPU。如果多个这样的测试并行运行,可能导致系统资源耗尽。
例如,在一个项目中,testStressTest会创建大量线程接近系统极限,当并行运行多个此类测试时就会失败。
功能尚未实现:在测试驱动开发(TDD)中,我们可能会先编写测试,然后再实现功能。在功能完成之前,这些测试应该被忽略。
第三方依赖问题:当我们的代码所依赖的外部服务或组件出现问题时,与之相关的测试可能需要暂时被跳过。
需要注意的是,忽略测试应该是一种临时措施,而不是长期解决方案。被忽略的测试应该定期审查,并尽快修复和重新启用。
在Jenkins中,有几种不同的方法可以忽略测试。每种方法都有其适用场景和优缺点。
大多数测试框架都提供了内置的忽略测试机制。例如,在JUnit中,你可以使用
@Ignore注解来跳过测试执行。
import org.junit.Ignore;
import org.junit.Test;
public class MyTest {
@Ignore("暂时跳过这个测试,因为相关功能还在开发中")
@Test
public void testFeatureUnderDevelopment() {
// 测试代码
}
@Test
public void testWorkingFeature() {
// 这个测试会正常执行
}
}
使用
@Ignore注解时,你可以提供可选的原因说明,解释为什么跳过这个测试。这有助于团队其他成员理解跳过测试的上下文。
当测试类中所有方法都需要跳过时,可以在类级别使用
@Ignore注解。
在某些情况下,我们可能希望根据特定条件决定是否跳过测试,例如只有在特定环境(如Travis CI)上运行时才跳过。
早期可能会这样实现:
protected JSCallGraph runTestExceptOnTravis(URL url, Object[][] assertions, BuilderType... builderTypes) throws WalaException, Error, CancelException {
if (System.getenv("TRAVIS") == null) {
return runTest(url, assertions, builderTypes);
} else {
return null;
}
}
但更恰当的做法是使用测试框架的条件跳过机制:
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assume.assumeThat;
// ...
protected void runTestExceptOnTravis(URL url, Object[][] assertions, BuilderType... builderTypes) throws WalaException, Error, CancelException {
assumeThat("not running on Travis CI", System.getenv("TRAVIS"), nullValue());
runTest(url, assertions, builderTypes);
}
使用
assumeThat方法,当条件不满足时(在Travis CI上运行),测试会显示为已跳过而不是通过,这样能更准确地反映测试状态。
Jenkins生态系统提供了多种插件,可以帮助我们更精细地控制测试执行。例如,可以使用Exclusion-Plugin来管理需要独占执行的测试。
对于像testStressTest这样创建大量线程的资源密集型测试,我们可以在Jenkins中这样配置:
使用Exclusion-Plugin创建一个资源,并分配给对应任务。添加一个Execute Shell构建步骤,运行除testStressTest外的所有测试。添加Critical Block Start构建步骤。添加另一个Execute Shell构建步骤,只运行testStressTest。添加Critical Block End构建步骤。在构建后操作中,配置合并测试报告。这种方法确保资源密集型测试不会并行执行,避免系统资源耗尽导致的虚假失败。
许多测试运行器支持通过命令行参数来过滤要执行的测试。例如,Ginkgo测试框架支持
-skip参数来跳过匹配特定模式的测试。
ginkgo -skip="create_public_ip"
需要注意的是,
-skip参数匹配的是测试用例中Describe函数提供的字符串,而不是测试文件名。如果Describe中的字符串与文件名不一致,可能会导致期望被跳过的测试没有被跳过。
让我们通过一个完整的示例,演示如何在Jenkins环境中实现测试的忽略。
假设我们有一个Java项目,使用Maven作为构建工具,JUnit作为测试框架。项目结构如下:
my-project/
├── pom.xml
├── src/
│ ├── main/
│ │ └── java/
│ │ └── com/
│ │ └── example/
│ │ └── Calculator.java
│ └── test/
│ └── java/
│ └── com/
│ └── example/
│ └── CalculatorTest.java
└── Jenkinsfile
我们的测试类包含多个测试方法,其中一个使用了
@Ignore注解:
package com.example;
import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.*;
public class CalculatorTest {
private Calculator calculator = new Calculator();
@Test
public void testAddition() {
assertEquals(5, calculator.add(2, 3));
System.out.println("执行加法测试");
}
@Test
public void testSubtraction() {
assertEquals(1, calculator.subtract(3, 2));
System.out.println("执行减法测试");
}
@Ignore("这个测试暂时跳过,因为除法功能尚未完全实现")
@Test
public void testDivision() {
assertEquals(2, calculator.divide(6, 3), 0.0001);
System.out.println("执行除法测试");
}
@Test
public void testMultiplication() {
assertEquals(6, calculator.multiply(2, 3));
System.out.println("执行乘法测试");
}
}
我们还可以添加一个根据环境变量条件性跳过的测试:
@Test
public void testDatabaseOperation() {
// 只有当数据库可用时才执行这个测试
assumeThat("数据库不可用,跳过测试",
System.getenv("DATABASE_AVAILABLE"),
is("true"));
// 数据库操作测试代码
System.out.println("执行数据库操作测试");
}
在Jenkinsfile中,我们可以配置流水线来自动化构建和测试过程:
pipeline {
agent any
environment {
DATABASE_AVAILABLE = 'false'
}
stages {
stage('Build') {
steps {
sh 'mvn compile'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
}
}
当我们在Jenkins中运行这个流水线时,Maven Surefire插件会执行测试,并生成测试报告。在测试结果中:
testAddition、testSubtraction和testMultiplication测试会显示为通过testDivision测试会显示为已跳过,并显示我们提供的理由testDatabaseOperation测试也会显示为已跳过,因为环境变量DATABASE_AVAILABLE设置为'false'在Jenkins测试趋势图中,被忽略的测试不会计入失败或通过,而是有单独的跳过统计。这有助于团队跟踪被跳过的测试数量,确保这些测试不会被遗忘。
虽然忽略测试是一个有用的功能,但不当使用可能导致问题。以下是一些最佳实践:
总是提供忽略理由:当忽略测试时,务必提供清晰的理由说明为什么跳过这个测试。这有助于其他开发人员理解上下文。
定期审查被忽略的测试:建立流程定期审查被忽略的测试,决定是否需要修复并重新启用,或者是否应该删除。被忽略的测试不应该成为代码库中的“永久居民”。
区分忽略测试和条件测试:对于因环境问题需要跳过的测试,考虑使用条件测试(如JUnit的assumeThat)而不是完全忽略。这样,当环境满足条件时,测试会自动执行。
在团队中统一策略:确保团队对何时忽略测试、如何记录理由以及何时重新启用测试有统一的策略。
优先修复不稳定的测试:如果测试因为不稳定(flaky)而被忽略,应该优先修复它们。不稳定的测试会削弱测试套件的价值,并可能导致团队忽视真实的失败。
考虑使用测试切片:对于大型测试套件,可以考虑使用测试切片(test slicing)技术,将测试分配到多个节点上并行执行。在这种情况下,可以跳过不属于当前切片的测试。
在Jenkins中可视化:确保Jenkins配置正确显示被跳过的测试,并与团队共享这些信息。可视化有助于跟踪技术债务。
在实践中,我们可能会遇到各种与忽略测试相关的问题。以下是一些常见问题及其解决方案:
问题1:被忽略的测试被遗忘
解决方案:在项目管理工具(如Jira)中为每个被忽略的测试创建任务,并分配给相应的开发人员。定期审查这些任务。
问题2:忽略测试导致测试覆盖度下降
解决方案:如果测试覆盖度很重要,可以考虑为被忽略的测试提供简化版或模拟版本的实现,保持覆盖度。
问题3:条件测试逻辑过于复杂
解决方案:将条件测试逻辑封装在专用的工具类或方法中,避免测试方法本身变得难以阅读和维护。
问题4:Ginkgo测试框架中-skip参数不工作
解决方案:记住Ginkgo的-skip参数匹配的是Describe函数中的字符串,而不是文件名。确保使用的字符串与Describe函数中的完全匹配。
问题5:资源密集型测试干扰其他测试
解决方案:使用Jenkins的Exclusion-Plugin等工具,确保资源密集型测试不会并行执行。
Jenkins中的忽略测试功能是一个强大的工具,当正确使用时,可以帮助团队保持持续集成流程的顺畅运行。
它允许我们临时跳过有问题的测试,而不是让整个构建失败。
但重要的是要记住,忽略测试应该是临时措施,而不是长期解决方案。
通过结合使用Jenkins的功能和测试框架的特性,我们可以创建一个健壮且高效的测试流程,既能提供快速反馈,又能保持代码质量。
正如一位开发者在一篇关于Jenkins的课程描述中提到的,Jenkins能够“帮助开发人员早期发现错误和bug,并更迅速地部署”。
而合理使用忽略测试功能,正是实现这一目标的重要技术之一。
最后,请记住:忽略测试就像是按下暂停键,而不是停止键。 它的目的是让你有机会解决问题,而不是逃避问题。明智地使用这个功能,你的CI/CD流程会更加健康高效。
¥47.00
PC游戏正版中文Steam 隐世神剑传 国区激活码cdk 秒发
¥153.00
Steam游戏 索尼克缤纷色彩 Sonic Colors:Ultimate 究极 索尼克缤纷世界 PC中文正版 激活码cdkey
¥21.80
PC正版 steam平台 国区 游戏 黑暗领域2 The Darkness II 激活码
¥31.00
汉匈决战 汉匈对决 戎马丹心 PC骑砍 骑马与砍杀骑砍系列 STEAM 正版 骑砍DLC 国区激活码
¥28.00
Steam正版PC中文游戏智械黎明DLC 群星Stellaris 激活码cdk
¥109.00
steam游戏PC中文正版 古墓丽影11暗影 国区激活码 CDK Shadow of the Tomb Raide