软件工程实践——从JUnit入门到三角形测试用例设计

📅 2026/7/14 12:31:42
软件工程实践——从JUnit入门到三角形测试用例设计
1. JUnit入门从零搭建测试环境第一次接触JUnit时我盯着那个绿色进度条看了足足三分钟——原来这就是单元测试的魅力。作为Java开发者最熟悉的测试框架JUnit能让你像搭积木一样构建测试用例。先来看看如何快速搭建环境在Eclipse中新建Java项目时记得勾选Add JUnit library。如果忘了也没关系右键项目 Build Path Add Libraries就能补装。我习惯用JUnit 5最新版但很多老项目还在用JUnit 4。两者的主要区别是注解写法比如Test注解在JUnit 5不需要再导入org.junit包。// JUnit 5基础测试模板 import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; class BasicTest { Test void shouldReturnTrueWhenConditionMet() { assertTrue(5 3, 这个数学常识居然出错了); } }新手常踩的坑是忘记测试方法的void返回类型和public修饰符JUnit 4要求。最近帮同事排查一个测试方法不执行的问题最后发现他把Test拼成了Text这种低级错误连IDE都不会报警。2. 三角形案例从需求到测试设计去年重构一个图形计算工具时三角形类型判断让我掉了不少头发。先看核心业务逻辑public class Triangle { private double a, b, c; public Triangle(double a, double b, double c) { this.a a; this.b b; this.c c; } public String getType() { if (!isValid()) return 非三角形; if (a b b c) return 等边三角形; if (a b || b c || a c) { return isRightAngle() ? 等腰直角三角形 : 等腰三角形; } return isRightAngle() ? 直角三角形 : 普通三角形; } private boolean isValid() { /* 验证边长有效性 */ } private boolean isRightAngle() { /* 勾股定理验证 */ } }设计测试用例时我画了张思维导图无效输入零、负数、非数字、两边之和等于第三边边界情况Double.MAX_VALUE、浮点精度误差比如1.0和0.9999999999999999正常情况等边/等腰/直角/普通三角形的排列组合3. 测试用例设计方法论有次代码评审时组长问我你的测试用例覆盖所有分支了吗这才意识到测试不是凭感觉。后来我总结出这套方法3.1 等价类划分把输入数据分成若干类每类选代表值测试。比如三角形边长有效类正实数组合无效类负数、零、非数字、字符串Test void should_ReturnNotTriangle_When_InputHasZero() { assertEquals(非三角形, new Triangle(0, 2, 3).getType()); }3.2 边界值分析在等价类边界上容易出bug比如最小值边界Double.MIN_VALUE浮点精度边界1.0和0.9999999999999999应该视为相等Test void should_HandlePrecisionIssue_When_SidesAreClose() { double epsilon 0.000000000000001; assertEquals(等边三角形, new Triangle(1.0, 1.0, 1.0 - epsilon).getType()); }3.3 错误推测法根据经验预测可能出错点忘记验证边长是否为数字勾股定理判断时没考虑浮点精度等腰直角判断顺序错误4. 测试进阶技巧有次发现测试随机失败原来是共享测试数据导致的。这些经验值得分享4.1 测试生命周期BeforeEach我在这里初始化测试数据AfterEach清理数据库连接等资源避免在静态字段保存状态会导致测试间相互污染4.2 参数化测试用ParameterizedTest减少重复代码ParameterizedTest CsvSource({ 3,4,5,直角三角形, 2,2,3,等腰三角形 }) void should_ReturnCorrectType(double a, double b, double c, String type) { assertEquals(type, new Triangle(a, b, c).getType()); }4.3 断言技巧assertAll组合多个断言避免第一个失败就停止assertThrows验证异常自定义匹配器比如用Hamcrest的closeTo处理浮点误差5. 测试驱动开发(TDD)实践去年用TDD开发日历组件时收获意外之喜——代码缺陷率下降40%。具体实施步骤先写失败测试红阶段Test void should_ReturnFebruaryDays_When_LeapYear() { fail(未实现闰年判断); }写最少代码使测试通过绿阶段public int getFebruaryDays(int year) { return 28; // 先写死返回值 }重构代码保持测试通过public int getFebruaryDays(int year) { if (year % 400 0) return 29; if (year % 100 0) return 28; return year % 4 0 ? 29 : 28; }TDD的节奏就像在玩红绿灯游戏关键是保持小步快跑。我习惯每个测试方法不超过10行每个生产方法对应3-5个测试用例。