Introduction
JUnit est un framework de test unitaire et un framework de test de régression pour le langage de programmation Java .
Fonctionnalités de JUnit :
- cadre open source
- Fournir des annotations pour identifier les méthodes de test
- Fournir des assertions pour tester les résultats attendus
- TestRun est fourni pour exécuter des tests.
- Courez vite, élégant et simple
- Peut s'exécuter automatiquement, vérifier ses propres résultats et fournir un retour immédiat
utiliser
Affirmation
L'assertion est la fonction principale de JUnit, et toutes les assertions de JUnit sont contenues dans la classe Assert.
Les principales méthodes de la classe Assert sont les suivantes :
nom de la méthode | description de la méthode |
---|---|
assertEquals | Affirmer que la valeur attendue transmise est égale à la valeur réelle |
assertNotEquals | Affirmer que la valeur attendue transmise n'est pas égale à la valeur réelle |
assertArrayEquals | Affirmer que le tableau attendu transmis est égal au tableau réel |
assertNull | Affirmer que l'objet transmis est nul |
assertNotNull | Affirmer que l'objet transmis n'est pas nul |
assertTrue | affirmer que la condition est vraie |
assertFalse | Affirmer que la condition est fausse |
assertSame | Affirmer que deux objets font référence au même objet, équivalent à "==" |
assertNotSame | Affirmer que deux objets font référence à des objets différents, équivalent à "!=" |
affirmer que | Confirme si une valeur réelle satisfait une condition spécifiée |
Remarque : Les méthodes ci-dessus sont toutes des méthodes statiques de Assert, appelées par Assert.xxx
, si vous devez appeler directement, vous devez ajouterimport static org.junit.Assert.*;
ordre d'exécution
Dans JUnit, l'ordre d' exécution est déterminé par les annotations @BeforeClass
, @Before
, et .@Test
@After
@AfterClass
annotation | introduire |
---|---|
@beforeClass() |
Les méthodes annotées sont exécutées en premier, et une seule fois. |
@afterClass() |
Les méthodes annotées sont exécutées en dernier et une seule fois. |
@before() |
Les méthodes annotées sont exécutées pour chaque cas de test, mais avant que le cas de test ne soit exécuté. |
@after() |
Les méthodes annotées sont exécutées pour chaque cas de test, mais après l'exécution du cas de test. |
@Test |
Entre la méthode before() et la méthode after(), chaque cas de test est exécuté. L'ordre d'exécution est déterminé par l'emplacement du code |
Les exemples sont les suivants :
@BeforeClass
public static void beforeClass() {
System.out.println("in before class");
}
//execute only once, in the end
@AfterClass
public static void afterClass() {
System.out.println("in after class");
}
//execute for each test, before executing test
@Before
public void before() {
System.out.println("in before");
}
//execute for each test, after executing test
@After
public void after() {
System.out.println("in after");
}
//test case 1
@Test
public void testCase1() {
System.out.println("in test case 1");
}
//test case 2
@Test
public void testCase2() {
System.out.println("in test case 2");
}
Le résultat est montré dans la figure:
écrire des tests
Voici le programme de chiffrement que nous allons tester
public class Encryption {
/**
* 加密程序,算法是将字符串反转,如 abc 会转为为 cba
* @param content
* @return
*/
public static String encryption(String content){
if (content == null)throw new NullPointerException();
if (content.length() < 2)return content;
char[] data = content.toCharArray();
int size = data.length;
for (int i = 0; i < size/2; i++) {
char c = data[i];
data[i] = data[size - i - 1];
data[size - i - 1] = c;
}
return new String(data);
}
}
Le code de test est le suivant
public class EncryptionTest {
String content = "abc";
@Test
public void encryption() {
assertEquals(Encryption.encryption(content),"cba");
}
}
essai paramétrique
Dans le code de test ci-dessus, il est très difficile de définir la valeur correspondante à chaque fois qu'une méthode est testée. Junit 4 introduit un nouveau test fonctionnel paramétré. Les tests paramétrés permettent aux développeurs d'exécuter le même test encore et encore avec des valeurs différentes. Vous suivrez 5 étapes pour créer des tests paramétrés.
- Utilisez
@RunWith(Parameterized.class)
pour annoterEncryptionTest
la classe. - Créez une
@Parameterized.Parameters
méthode statique publique annotée qui renvoie une collection (tableau) d'objets à utiliser comme collection de données de test. - Créez un constructeur public pour EncryptionTest qui accepte l'équivalent d'une ligne de données de test.
- Créez une variable d'instance pour chaque colonne de données de test.
- Créez vos cas de test en utilisant des variables d'instance comme source de données de test.
code afficher comme ci-dessous:
@RunWith(Parameterized.class)
public class EncryptionTest {
String result;
String content;
public EncryptionTest(String content, String result) {
this.content = content;
this.result = result;
}
@Parameterized.Parameters
public static Collection primeNumbers(){
return Arrays.asList(new Object[][]{
{
"abc","cba"},
{
"1234","4321"},
{
"",""}
});
}
@Test
public void encryption() {
System.out.println("content = "+content+" result = "+result);
assertEquals(Encryption.encryption(content),result);
}
}
Les résultats des tests sont présentés dans la figure :
test d'exception
Lorsque nous entrons dans content = null
, une exception sera levée. Alors, comment testons-nous les conditions anormales, cela nécessite l'utilisation de paramètres @Test
d'annotation expected
, la valeur du paramètre est l'anomalie à détecter. Si l'exception correspondante est levée, le test réussit ; sinon, le test échoue.
code afficher comme ci-dessous:
@Test(expected = NullPointerException.class)
public void encryption() {
System.out.println("content = "+content+" result = "+result);
assertEquals(Encryption.encryption(content),result);
}
essai de temps
Parfois, nous devons tester l'efficacité d'un certain module, nous devons tester le temps d'exécution. Nous pouvons timeout
déterminer le temps d'exécution maximal en millisecondes grâce aux paramètres de @Test.
code afficher comme ci-dessous:
@Test(timeout = 1000)
public void encryption() {
System.out.println("content = "+content+" result = "+result);
assertEquals(Encryption.encryption(content),result);
}
test asynchrone
Principe : le principe des tests asynchrones consiste à bloquer le thread de test, puis à exécuter le thread de test après l'exécution du thread asynchrone.
Ici utilisation wait
et notiftyAll
méthode à réaliser, le code est le suivant
/**
*要测试的类
*/
public class Simple {
public interface Callback{
void finish(String result);
}
private Callback callback;
public void setCallback(Callback callback) {
this.callback = callback;
}
public void deal(){
new Thread(){
@Override
public void run() {
try {
//模拟耗时操作
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
callback.finish("完成");
}
}.start();
}
}
/**
*测试类
*/
public class SimpleTest {
private Object lock = new Object();
private int flag = 0;
String res = null;
@Test
public void deal(){
Simple simple = new Simple();
simple.setCallback(result -> {
synchronized (lock){
flag = 1;
lock.notifyAll();
}
res = result;
});
simple.deal();
synchronized (lock){
while (flag == 0){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
assertEquals(res,"完成");
}
}
affirmer que
Transfert des tests unitaires Android (1) :assertThat
l'utilisation du framework JUnit
Certaines des assertions de base que nous avons utilisées ci-dessus, si nous ne définissons pas les informations de sortie lorsque l'échec se produit, alors seule une AssertionError sera levée lorsque l'assertion échoue, et il est impossible de savoir quelle partie est erronée. Et assertThat nous aide à résoudre ce problème. C'est plus lisible.
assertThat(T actual, Matcher<? super T> matcher);
assertThat(String reason, T actual, Matcher<? super T> matcher);
Parmi eux, raison est l'information de sortie lorsque l'assertion échoue, réel est la valeur de l'assertion et matcher est le matcher de l'assertion.
Classements de matcher couramment utilisés :
matcher | illustrer | exemple |
---|---|---|
est | Affirme que l'argument est égal à l'expression de correspondance donnée plus tard | assertThat(5, est (5)); |
pas | Affirmer que l'argument n'est pas égal à l'expression correspondante donnée plus tard assertThat(5, not(6)); | |
égal à | Les arguments d'assertion sont égaux | assertThat(30, equalTo(30)); |
equalToIgnoringCase | Affirmer l'égalité des chaînes en ignorant la casse | assertThat("Ab", equalToIgnoringCase("ab")); |
contientString | Affirmer qu'une chaîne contient une chaîne | assertThat("abc", containsString("bc")); |
commence avec | Affirmer qu'une chaîne commence par une certaine chaîne | assertThat("abc", commencePar("a")); |
se termine par | Affirmer qu'une chaîne se termine par une certaine chaîne | assertThat("abc", se termine par("c")); |
valeur null | Affirmer que la valeur du paramètre est null | assertThat(null, nullValue()); |
notNullValue | Affirmer que la valeur du paramètre n'est pas nulle | assertThat("abc", notNullValue()); |
plus grand que | Affirmer que l'argument est supérieur à | assertThat(4, supérieur(3)); |
moins que | Affirmer que l'argument est inférieur à | assertThat(4, moinsQue(6)); |
Plus grand ou égal à | Affirmer que l'argument est supérieur ou égal à | assertThat(4,supérieuràouégalà(3)); |
inférieur ou égal à | Affirmer que l'argument est inférieur ou égal à | assertThat(4, lessThanOrEqualTo(6)); |
proche de | Affirmer qu'un nombre à virgule flottante se trouve dans une certaine plage | assertThat(4.0, closeTo(2.6, 4.3)); |
tous | Affirmer que toutes les conditions sont remplies, équivalent à && | assertThat(4,allOf(greaterThan(3), lessThan(6))); |
n'importe quel | Affirmer qu'une condition est remplie, équivalente ou | assertThat(4,anyOf(greaterThan(9), lessThan(6))); |
hasKey | 断言Map集合含有此键 | assertThat(map, hasKey(“key”)); |
hasValue | 断言Map集合含有此值 | assertThat(map, hasValue(value)); |
hasItem | 断言迭代对象含有此元素 | assertThat(list, hasItem(element)); |
下图为使用assertThat测试失败时所显示的具体错误信息。可以看到错误信息很详细!
当然了匹配器也是可以自定义的。这里我自定义一个字符串是否是手机号码的匹配器来演示一下。
只需要继承BaseMatcher抽象类,实现matches与describeTo方法。代码如下:
public class IsMobilePhoneMatcher extends BaseMatcher<String> {
/**
* 进行断言判定,返回true则断言成功,否则断言失败
*/
@Override
public boolean matches(Object item) {
if (item == null) {
return false;
}
Pattern pattern = Pattern.compile("(1|861)(3|5|7|8)\\d{9}$*");
Matcher matcher = pattern.matcher((String) item);
return matcher.find();
}
/**
* 给期待断言成功的对象增加描述
*/
@Override
public void describeTo(Description description) {
description.appendText("预计此字符串是手机号码!");
}
/**
* 给断言失败的对象增加描述
*/
@Override
public void describeMismatch(Object item, Description description) {
description.appendText(item.toString() + "不是手机号码!");
}
}
@Rule用法
转自Android单元测试(一):JUnit框架的使用的@Rule用法
还记得一开始我们在@Before与@After注解的方法中加入”测试开始”的提示信息吗?假如我们一直需要这样的提示,那是不是需要每次在测试类中去实现它。这样就会比较麻烦。这时你就可以使用@Rule来解决这个问题,它甚至比@Before与@After还要强大。
自定义@Rule很简单,就是实现TestRule 接口,实现apply方法。代码如下:
public class MyRule implements TestRule {
@Override
public Statement apply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
// evaluate前执行方法相当于@Before
String methodName = description.getMethodName(); // 获取测试方法的名字
System.out.println(methodName + "测试开始!");
base.evaluate(); // 运行的测试方法
// evaluate后执行方法相当于@After
System.out.println(methodName + "测试结束!");
}
};
}
}
我们使用一下我们自定义的MyRule,效果如图:
JUnit - 框架扩展
Cactus
Cactus 是一个简单框架用来测试服务器端的 Java 代码(Servlets, EJBs, Tag Libs, Filters)。Cactus 的设计意图是用来减小为服务器端代码写测试样例的成本。它使用 JUnit 并且在此基础上进行扩展。Cactus 实现了 in-container 的策略,意味着可以在容器内部执行测试。
JWebUnit
JWebUnit est un framework de test basé sur Java pour les applications Web. Il intègre des frameworks existants tels que HtmlUnit et Selenium avec une interface de test unifiée et simple pour vous permettre de tester rapidement l'exactitude des applications Web.
JWebUnit fournit une API Java de haut niveau pour travailler avec des applications Web qui intègre une série d'assertions qui vérifient l'exactitude du programme. Cela inclut la transmission de liens, le remplissage et la soumission de formulaires, la validation du contenu du formulaire et d'autres fonctionnalités commerciales typiques des applications Web.
XMLUnit
XMLUnit fournit une seule classe d'extension JUnit, XMLTestCase, et quelques classes de support qui autorisent les assertions :
- Comparez deux fichiers XML pour les différences (en utilisant les classes Diff et DetailsDiff)
- Validation d'un fichier XML (en utilisant la classe Validator)
- Le résultat de la transformation d'un fichier XML à l'aide de XSLT (en utilisant la classe Transform)
- Évaluation des expressions XPath pour un document XML (en implémentant l'interface XPathEngine)
- Un nœud autonome après la traversée DOM d'un fichier XML (en utilisant la classe NodeTest)
ObjetMock
Dans un test unitaire, les objets factices peuvent imiter le comportement d'objets complexes et réels (non factices). Ils sont donc utiles lorsqu'un objet réel est peu pratique ou impossible à inclure dans un test unitaire.