使用JUnitParams进行参数化的JUnit测试
參數化的單元測試用于在不同條件下測試相同的代碼。 借助參數化的單元測試,我們可以建立一種測試方法,該方法從某些數據源中檢索數據。 該數據源可以是測試數據對象,外部文件甚至數據庫的集合。 一般的想法是使使用相同的單元測試方法測試不同的條件變得容易,這將限制我們需要編寫的源代碼并使測試代碼更健壯。 我們可以將這些測試稱為數據驅動的單元測試。
在JUnit中實現數據驅動的單元測試的最佳方法是使用JUnit的自定義運行器- Parameterized或JUnitParams的 JUnitParamsRunner 。 使用JUnit的方法可能在許多情況下都可行,但是后者似乎更易于使用且功能更強大。
基本例子
在我們的示例中,一個撲克骰子,我們需要計算滿屋的得分。 就像紙牌撲克一樣,“滿座”是一副擲骰子,您同時擁有3個和一對。 為了簡單起見,分數是一卷中所有骰子的總和。 因此,讓我們看一下代碼:
class FullHouse implements Scoreable {@Overridepublic Score getScore(Collection dice) {Score pairScore = Scorables.pair().getScore(dice);Score threeOfAKindScore = Scorables.threeOfAKind().getScore(pairScore.getReminder());if (bothAreGreaterThanZero(pairScore.getValue(), threeOfAKindScore.getValue())) {return new Score(pairScore.getValue() + threeOfAKindScore.getValue()); // no reminder}return new Score(0, dice);}private boolean bothAreGreaterThanZero(int value1, int value2) {return value1 > 0 && value2 > 0;} }我想確保該擲骰正確得分(當然我已經對Pair和ThreeOfAKind進行了單元測試)。 因此,我想測試以下條件:
- 分數是11:1、1、3、3、3
- 2、2、2、1、1的得分是8
- 分數是0代表:2、3、4、1、1
- 分數是25,表示:5、5、5、5、5
讓我們研究為該方法編寫數據驅動的測試的兩種可能方法。 首先, JUnit的參數化 :
@RunWith(Parameterized.class) public class FullHouseTest {private Collection rolled;private int score;public FullHouseTest(Collection rolled, int score) {this.rolled = rolled;this.score = score;}@Testpublic void fullHouse() {assertThat(new FullHouse().getScore(rolled).getValue()).isEqualTo(score);}@Parameterized.Parameterspublic static Iterable data() {return Arrays.asList(new Object[][]{{roll(1, 1, 3, 3, 3), score(11)},{roll(2, 2, 2, 1, 1), score(8)},{roll(2, 3, 4, 1, 1), score(0)},{roll(5, 5, 5, 5, 5), score(25)}});}private static int score(int score) {return score;} }另一個是JUnitParams :
@RunWith(JUnitParamsRunner.class) public class FullHouseTest {@Test@Parameterspublic void fullHouse(Collection rolled, int score) {assertThat(new FullHouse().getScore(rolled).getValue()).isEqualTo(score);}public Object[] parametersForFullHouse() {return $($(roll(1, 1, 3, 3, 3), score(11)),$(roll(2, 2, 2, 1, 1), score(8)),$(roll(2, 3, 4, 1, 1), score(0)),$(roll(5, 5, 5, 5, 5), score(25)));}private static int score(int score) {return score;} }乍一看,兩者看起來非常相似。 沒錯 那么JUnit Parameterized (1)和JUnitParams(2)之間有什么區別? 最重要的一種是傳遞參數的方法,因此實際上是解決方案的體系結構。 在(1)中,參數在構造函數中傳遞,而在(2)中,參數直接傳遞到測試方法。 我應該在乎嗎? 是。 原因之一是,在(2)中,我們可以有多個參數化測試方法,每種方法的數據都不同,如以下示例所示:
@RunWith(JUnitParamsRunner.class) public class NumberOfAKindTest {@Test@Parameterspublic void pair(Collection rolled, int[] expected, int score) {NumberOfAKind sut = new NumberOfAKind(2);doTest(rolled, expected, score, sut);}@Test@Parameterspublic void threeOfAKind(Collection rolled, int[] expected, int score) {NumberOfAKind sut = new NumberOfAKind(3);doTest(rolled, expected, score, sut);}public Object[] parametersForPair() {return $($(roll(1, 1, 1, 2, 3), hand(1, 1), score(2)),$(roll(2, 1, 1, 1, 1), hand(1, 1), score(2)),$(roll(2, 3, 4, 1, 1), hand(1, 1), score(2)),$(roll(2, 3, 5, 5, 5), hand(5, 5), score(10)),$(roll(2, 1, 5, 4, 3), null, score(0)));}public Object[] parametersForThreeOfAKind() {return $($(roll(1, 1, 1, 2, 3), hand(1, 1, 1), score(3)),$(roll(2, 1, 1, 1, 3), hand(1, 1, 1), score(3)),$(roll(2, 3, 1, 1, 1), hand(1, 1, 1), score(3)),$(roll(2, 3, 5, 5, 5), hand(5, 5, 5), score(15)),$(roll(2, 5, 5, 5, 6), hand(5, 5, 5), score(15)),$(roll(2, 2, 5, 5, 3), null, score(0)));}private static int[] hand(int... dice) {return dice;}private static int score(int score) {return score;}}在更簡單的示例中,可以通過值方法直接在@Parameters批注中將參數定義為String數組。 我們還可以將數據提取到一個外部類中,并使我們的測試更加清晰易讀。 NumberOfAKind的完整測試如下:
@RunWith(JUnitParamsRunner.class) public class NumberOfAKindTest {@Test@Parameters(source = NumberOfAKindProvider.class, method = "providePair")public void pair(Collection rolled, int[] expected, int score) {NumberOfAKind sut = new NumberOfAKind(2);doTest(rolled, expected, score, sut);}@Test@Parameters(source = NumberOfAKindProvider.class, method = "provideThreeOfAKind")public void threeOfAKind(Collection rolled, int[] expected, int score) {NumberOfAKind sut = new NumberOfAKind(3);doTest(rolled, expected, score, sut);}@Test@Parameters(source = NumberOfAKindProvider.class, method = "provideFourOfAKind")public void fourOfAKind(Collection rolled, int[] expected, int score) {NumberOfAKind sut = new NumberOfAKind(4);doTest(rolled, expected, score, sut);}@Test@Parameters(source = NumberOfAKindProvider.class, method = "provideFiveOfAKind")public void fiveOfAKind(Collection rolled, int[] expected, int score) {NumberOfAKind sut = new NumberOfAKind(5);doTest(rolled, expected, score, sut);}private void doTest(Collection rolled, int[] expected, int score, NumberOfAKind sut) {Collection consecutiveDice = sut.getConsecutiveDice(rolled);assertDiceContainsValues(consecutiveDice, expected);assertThat(sut.getScore(rolled).getValue()).isEqualTo(score);}private void assertDiceContainsValues(Collection dice, int[] expected) {Collection values = toInts(dice);if (expected == null) {assertThat(values).isEmpty();return;}for (int i = 0; i < expected.length; i++) {assertThat(values).hasSize(expected.length).contains(expected[i]);}}private Collection toInts(Collection dice) {return Collections2.transform(dice, new Function() {@Overridepublic Integer apply(Dice input) {return input.getValue();}});}}每個方法都指定提供程序類和提供程序的方法名稱。 查看以下提供者:
public class NumberOfAKindProvider {public static Object[] providePair() {return $($(roll(1, 1, 1, 2, 3), hand(1, 1), score(2)),$(roll(2, 1, 1, 1, 1), hand(1, 1), score(2)),$(roll(2, 3, 4, 1, 1), hand(1, 1), score(2)),$(roll(2, 3, 5, 5, 5), hand(5, 5), score(10)),$(roll(2, 1, 5, 4, 3), null, score(0)));}public static Object[] provideThreeOfAKind() {return $($(roll(1, 1, 1, 2, 3), hand(1, 1, 1), score(3)),$(roll(2, 1, 1, 1, 3), hand(1, 1, 1), score(3)),$(roll(2, 3, 1, 1, 1), hand(1, 1, 1), score(3)),$(roll(2, 3, 5, 5, 5), hand(5, 5, 5), score(15)),$(roll(2, 5, 5, 5, 6), hand(5, 5, 5), score(15)),$(roll(2, 2, 5, 5, 3), null, score(0)));}public static Object[] provideFourOfAKind() {return $($(roll(1, 1, 1, 1, 3), hand(1, 1, 1, 1), score(4)),$(roll(2, 1, 1, 1, 1), hand(1, 1, 1, 1), score(4)),$(roll(2, 5, 5, 5, 5), hand(5, 5, 5, 5), score(20)),$(roll(2, 3, 4, 5, 5), null, score(0)));}public static Object[] provideFiveOfAKind() {return $($(roll(1, 1, 1, 1, 1), hand(1, 1, 1, 1, 1), score(5)),$(roll(6, 6, 6, 6, 6), hand(6, 6, 6, 6, 6), score(30)),$(roll(6, 6, 6, 6), null, score(0)),$(roll(2, 3, 4, 6, 6), null, score(0)));}private static int[] hand(int... dice) {return dice;}private static int score(int score) {return score;} }摘要
對我來說, JUnitParams是編寫良好的數據驅動的單元測試的更好的解決方案。 但是上面介紹的并不是庫必須提供給開發人員的所有內容。 還有更多功能。 參數可以作為CSV字符串傳遞,我們可以混合參數化測試和非參數化測試,僅舉幾例。
請訪問該項目的網站以了解有關此庫的更多信息: https : //code.google.com/p/junitparams
翻譯自: https://www.javacodegeeks.com/2013/12/parameterized-junit-tests-with-junitparams.html
總結
以上是生活随笔為你收集整理的使用JUnitParams进行参数化的JUnit测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怀化特产(来怀化旅游,这九大美食千万不要
- 下一篇: 辅助巨魔天赋符文天赋符文天赋(lol巨魔