junit junit
您读过数学理论吗?
它通常读取如下内容:
对于所有a,b> 0满足以下条件:a + b> a和a + b> b
通常,这些语句更难以理解。
这种陈述有一些有趣的地方:它适用于相当大(在这种情况下为无限)集合的每个元素(或元素组合)。
将其与典型测试的陈述进行比较:
@Test
public void a_plus_b_is_greater_than_a_and_greater_than_b(){
int a = 2;
int b = 3;
assertTrue(a + b > a);
assertTrue(a + b > b);
}
这仅是关于我们所讨论的大集合中单个元素的陈述。 不太令人印象深刻。 当然,我们可以通过遍历测试(或使用参数化测试 )来解决此问题:
@Test
public void a_plus_b_is_greater_than_a_and_greater_than_b_multiple_values() {
List<Integer> values = Arrays.asList(1, 2, 300, 400000);
for (Integer a : values)
for (Integer b : values) {
assertTrue(a + b > a);
assertTrue(a + b > b);
}
}
当然,这仍然仅测试了一些值,但是也变得非常难看。 我们正在使用9行代码来测试数学家在一行中写的内容! 这种关系对于任何值a,b都应保持的要点在翻译中完全消失了。
但是仍然有希望: JUnit理论 。 让我们看看使用该漂亮工具的测试情况:
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertTrue;
@RunWith(Theories.class)
public class AdditionWithTheoriesTest {
@DataPoints
public static int[] positiveIntegers() {
return new int[]{
1, 10, 1234567};
}
@Theory
public void a_plus_b_is_greater_than_a_and_greater_than_b(Integer a, Integer b) {
assertTrue(a + b > a);
assertTrue(a + b > b);
}
}
使用JUnit理论,测试分为两个独立部分:提供数据点(即用于测试的值)的方法以及理论本身。 该理论看起来几乎像是一个测试,但是它具有不同的注释(@Theory)并且需要参数。 类中的理论将与数据点的每种可能组合一起执行。
这意味着,如果我们对测试主题有一个以上的理论,则只需声明数据点一次。 因此,让我们添加以下理论,这对于加法而言应该是正确的:a + b = b + a因此,我们将以下理论添加到我们的类@Theory中public void add_is_commutative(Integer a,Integer b){assertTrue(a + b == b + a); }
这就像一种魅力,并且可以开始看到它实际上也节省了一些代码,因为我们不重复数据点。 但是,我们仅使用正整数进行测试,而可交换属性应适用于所有整数! 当然,我们的第一个理论仍然只适用于正数
也有一个解决方案: 假设 。 假设您可以检查理论的先决条件。 如果对于给定的参数集不正确,则该理论将被跳过。 所以我们的测试现在看起来像这样:
@RunWith(Theories.class)
public class AdditionWithTheoriesTest {
@DataPoints
public static int[] integers() {
return new int[]{
-1, -10, -1234567,1, 10, 1234567};
}
@Theory
public void a_plus_b_is_greater_than_a_and_greater_than_b(Integer a, Integer b) {
Assume.assumeTrue(a >0 && b > 0 );
assertTrue(a + b > a);
assertTrue(a + b > b);
}
@Theory
public void addition_is_commutative(Integer a, Integer b) {
assertTrue(a + b == b + a);
}
}
这使测试表现力很好。
将测试数据与测试/理论实现分开,除了简洁以外,还可以带来另一个积极的效果:您可能会开始考虑与实际测试内容无关的测试数据。
让我们做到这一点。 如果要测试采用整数参数的方法,那么哪些整数可能会引起问题? 这是我的建议:
@DataPoints
public static int[] integers() {
return new int[]{
0, -1, -10, -1234567,1, 10, 1234567, Integer.MAX_VALUE, Integer.MIN_VALUE};}
在我们的示例中,哪个当然会导致测试失败。 如果在Integer.MAX_VALUE中添加一个正整数,则会溢出! 因此,我们刚刚得知我们目前的理论是错误的! 是的,我知道这很明显,但是请看一下当前项目中的测试。 使用整数的所有测试是否都以MIN_VALUE,MAX_VALUE,0,正值和负值测试? 是的,是这样。
那更复杂的对象呢? 琴弦? 日期? 收藏? 还是领域对象? 使用JUnit Theories,您可以设置测试数据生成器一次,以创建所有容易产生问题的场景,然后使用这些理论在所有测试中重用这些场景。 这将使您的测试更具表现力,并提高发现错误的可能性。
翻译自: https://www.javacodegeeks.com/2013/12/introduction-to-junit-theories.html
junit junit