闽公网安备 35020302035485号
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.8.0</version>
<scope>test</scope>
</dependency>
</dependencies>
然后,创建一个简单的计算器类,通常这里替换为你实际要测试的业务类:public class SimpleCalculator {
public int add(int a, int b) {
return a + b;
}
public int subtract(int a, int b) {
return a - b;
}
}
然后在 /test 的相同目录下创建对应的测试类import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class SimpleCalculatorTest {
// 堆代码 duidaima.com
// 在所有测试方法执行前,仅执行一次。这个方法需要是静态的。
@BeforeAll
static void setup() {
System.out.println("BeforeAll - 初始化共享资源,例如数据库连接");
}
// 在所有测试方法执行后,仅执行一次。这个方法需要是静态的。
@AfterAll
static void tearDown() {
System.out.println("AfterAll - 清理共享资源,例如关闭数据库连接");
}
// 在每个测试方法执行前,都会执行一次。用于设置测试方法所需的初始状态。
@BeforeEach
void init() {
System.out.println("BeforeEach - 初始化测试实例所需的数据");
}
// 在每个测试方法执行后,都会执行一次。用于清理测试方法使用的资源。
@AfterEach
void cleanup() {
System.out.println("AfterEach - 清理测试实例所用到的资源");
}
// 标注一个测试方法,用于测试某个功能。
@Test
void testAddition() {
System.out.println("Test - 测试加法功能");
SimpleCalculator calculator = new SimpleCalculator();
assertEquals(5, calculator.add(2, 3), "2 + 3 应该等于 5");
}
// 再添加一个测试方法
@Test
void testSubtraction() {
System.out.println("Test - 测试减法功能");
SimpleCalculator calculator = new SimpleCalculator();
assertEquals(1, calculator.subtract(3, 2), "3 - 2 应该等于 1");
}
}
以上程序,可以看到 Junit 常用注解使用说明:mvn test输出结果:
[INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running SimpleCalculatorTest BeforeAll - 初始化共享资源,例如数据库连接 BeforeEach - 初始化测试实例所需的数据 Test - 测试加法功能 AfterEach - 清理测试实例所用到的资源 BeforeEach - 初始化测试实例所需的数据 Test - 测试减法功能 AfterEach - 清理测试实例所用到的资源 AfterAll - 清理共享资源,例如关闭数据库连接 [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.058 s - in SimpleCalculatorTest [INFO] [INFO] Results: [INFO] [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------或者可以直接在 IDEA 中执行测试,如下:

public class MyStringUtil {
public String reverse(String input) {
if (input == null) {
return null;
}
return new StringBuilder(input).reverse().toString();
}
}
在静态测试类中,我们使用 @Test 定义 3 个方法来尝试覆盖 reverse() 可能得多种情况:import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class MyStringUtilStaticTest {
private MyStringUtil stringUtil = new MyStringUtil();
@Test
void reverseString() {
// 堆代码 duidaima.com
// 反转字符串 'hello'
assertEquals("olleh", stringUtil.reverse("hello"));
}
@Test
void reverseEmptyString() {
// 反转空字符串
assertEquals("", stringUtil.reverse(""));
}
@Test
void handleNullString() {
// 处理 null 字符串
assertEquals(null, stringUtil.reverse(null));
}
}
然后用动态测试来实现同样的测试用例:import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
public class MyStringUtilDynamicTest {
private MyStringUtil stringUtil = new MyStringUtil();
// 使用 @TestFactory 注解定义了一个动态测试工厂方法 reverseStringDynamicTests()
// 工厂方法返回一个 Collection<DynamicTest>
@TestFactory
Collection<DynamicTest> reverseStringDynamicTests() {
// 包含了 3 个动态测试用例,每个测试用例使用 dynamicTest() 方法创建
return Arrays.asList(
dynamicTest("动态测试:反转字符串 'hello'", () -> assertEquals("olleh", stringUtil.reverse("hello"))),
dynamicTest("动态测试:反转空字符串", () -> assertEquals("", stringUtil.reverse(""))),
dynamicTest("动态测试:处理 null 字符串", () -> assertEquals(null, stringUtil.reverse(null)))
);
}
}
在动态测试类中逻辑如下:public class BankAccount {
private double balance;
public BankAccount(double balance) {
this.balance = balance;
}
public void withdraw(double amount) {
assert amount > 0 : "Amount must be positive";
assert amount <= balance : "Insufficient balance";
balance -= amount;
assert balance >= 0 : "Balance can't be negative";
}
public double getBalance() {
return balance;
}
}
在这个示例中,我们使用了 Java 中的断言(assertion)来实现契约式设计。具体来说:
3.更高质量的交付:这里就不必多说了,通过测试的代码和没有测试的代码,是完全不一样的。未经测试的代码根本不具备上生产的条件
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
接下来,你需要选择一个SLF4J的实现,例如Logback或Log4j2,并将其添加到项目中。你可以在Maven或Gradle中添加以下依赖:<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
在代码中,你可以使用以下代码打印Hello World:import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
private static final Logger logger = LoggerFactory.getLogger(HelloWorld.class);
public static void main(String[] args) {
logger.info("Hello World");
}
}
这将使用SLF4J打印一条信息,其中包含“Hello World”字符串。你可以在控制台或日志文件中查看此信息。| 日志级别 | 内容 |
|---|---|
| TRACE | 用于跟踪程序的细节信息,通常用于调试。 |
| DEBUG | 用于调试程序,输出程序中的详细信息,例如变量的值、方法的调用等。 |
| INFO | 用于输出程序的运行状态信息,例如程序启动、关闭、连接数据库等。 |
| WARN | 用于输出警告信息,表示程序可能存在潜在的问题,但不会影响程序的正常运行。 |
| ERROR | 用于输出错误信息,表示程序发生了错误,包括致命错误。 |
不同的日志级别用于记录不同的信息。这样做的目的不仅可以减少不必要的日志输出和文件大小,还可以提供快速定位的能力,例如开发环境通常使用 TRACE、DEBUG 日志,生产环境通常使用 INFO,WARN 日志等。这些信息都可以在 logback.xml 日志配置文件里面配置。
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/myapp.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/var/log/myapp.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>
在此配置文件中,定义了两个 appender:| 工具名称 | Github 地址 |
|---|---|
| FindBugs | https://github.com/findbugsproject/findbugs |
| PMD | https://github.com/pmd/pmd |
| Checkstyle | https://github.com/checkstyle/checkstyle |
| SonarQube | https://github.com/SonarSource/sonarqube |
| IntelliJ IDEA | https://github.com/JetBrains/intellij-community/ |
3.静态扫描工具只能检查代码是否符合特定的规范和标准,但无法确保代码的质量和可读性。
3.可以促进团队协作和学习,通过分享和讨论代码,可以提高开发人员的技能和知识,并提高团队的凝聚力和效率。