自动化工具 断言神器 AssertJ 快速入门

胡刚 · 2016年05月18日 · 最后由 Teambition 回复于 2016年06月13日 · 897 次阅读
本帖已被设为精华帖!

1.背景

在设计自动化 cases 时,遵守的核心原则是 3A(Arrange-> Actor ->Assert)原则;

断言工具是否强大直接影响到用例的执行效率,本文将介绍一种流式断言神器:AssertJ。

在 JAVA cases 中常用的断言工具有 JUnit 自带的 Assert,还有 hamcrest 的 assertThat(之前总结过http://blog.csdn.net/neven7/article/details/42489723),这些工具对于 AssertJ 来说都相形见绌。

2.AssertJ 介绍

AseertJ: JAVA 流式断言器,什么是流式,常见的断言器一条断言语句只能对实际值断言一个校验点,而流式断言器,支持一条断言语句对实际值同时断言多个校验点。

AssertJ 支持如下模块:

Core:AssertJ core is a Java library that provides a fluent interface for writing assertions. 

Assertions generator:Use the Assertion Generator to create assertions specific to your own classes.

Guava:AssertJ assertions for Guava provides assertions for Guava types like Multimap, Table, Optional, Range or ByteSource.

Joda-Time:AssertJ assertions for Joda-Time provides assertions for Joda-Time types like DateTime and LocalDateTime.

DB:AssertJ-DB provides assertions to test data in a database.

Neo4j:Provides assertions for Neo4j 2 or higher.

Swing:AssertJ Swing is a Java library that provides a fluent interface for functional Swing UI testing.

3.AssertJ 使用

本文将主要介绍 Core 下常用的断言方法。

版本要求:

AssertJ major versions depend on different Java versions :

AssertJ 1.x requires Java 6 or higher (suitable for Android)
AssertJ 2.x requires Java 7 or higher (should be suitable for Android - please file an issue if it's not the case)
AssertJ 3.x requires Java 8 or higher (not suitable for Android due to Path assertions)

本文使用 JDK7, maven pom.xml 添加依赖:

<dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <!-- use 2.4.1 for Java 7 projects -->
            <version>2.4.1</version>
            <!-- <version>3.4.1</version> -->
            <scope>test</scope>
</dependency>

在 cases 中 import assertj

import static org.assertj.core.api.Assertions.*;

先介绍一个实例,比较类对象,用到了 isEqualToComparingFieldByFieldRecursively,嵌套比较字段值。

package com.weibo.qa.testcase.lab;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.testng.annotations.Test;

import static org.assertj.core.api.Assertions.*;

/**
 * 
 * 两个类对象比较
 * 
 * @author hugang
 *
 */
class A {
    List<String> list = new ArrayList<String>();
    String str;

}

class B {
    A aB = new A();
    String test;
}
public class AssertJTest {
    @Test
    public void testAssertJ() {

        A a1 = new A();
        A a2 = new A();

        a1.str = "hello";
        a2.str = "hello";

        a1.list.add("world");
        a2.list.add("world");

        B b1 = new B();
        B b2 = new B();


        b1.test = "b1";
        b2.test = "b1";

        b1.aB.list = a1.list;
        b1.aB.str = a1.str;

        b2.aB.list = a2.list;
        b2.aB.str = a2.str;


        // 不包含 对象类型
        assertThat(a1).isEqualToComparingFieldByField(a2);

        // 对象类型 只比较引用
        // assertThat(b1).isEqualToComparingFieldByField(b2);


        // 含有嵌式比较,含有对象类型的字段,再比较对象内的数据
        assertThat(b1).isEqualToComparingFieldByFieldRecursively(b2);

    }
}

常用的一些用法:

添加错误提示信息: as
assertThat("abc").as("校验abc").isEqualTo("abcd");

错误提示:
org.junit.ComparisonFailure: [校验abc] expected:<"abc[d]"> but was:<"abc[]">

链式校验.
// isEqualTo 相等, contains包含
assertThat("abc").as("校验abc").isEqualTo("abc").contains("d");

错误提示:
FAILED: testAssertJ
java.lang.AssertionError: [校验abc] 
Expecting:
 <"abc">
to contain:
 <"d"> 

null 判断
Object object = null;
assertThat(object).isNotNull();

AILED: testAssertJ
java.lang.AssertionError: 
Expecting actual not to be null


Object object = null;
assertThat(object).isNull();

是否在某个范围内

List list = new ArrayList();
assertThat(list).isIn(new ArrayList(), new HashMap());



assertThat(list).isNotIn(new ArrayList(), new HashMap());
java.lang.AssertionError: 
Expecting:
 <[]>
not to be in:
 <[[], {}]>

大小

List list = new ArrayList();

assertThat(list).hasSize(1);
FAILED: testAssertJ
java.lang.AssertionError: 
Expected size:<1> but was:<0> in:
<[]>

等等,实在太多了,等你来发掘。

可参见官方 wiki: http://joel-costigliola.github.io/assertj/index.html

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 8 条回复 时间 点赞

我估计 junit5 出来后会有更强的断言吧. 其实目前 scalatest 的 should 风格断言也非常的好. 比如

string should startWith ("Hello")
string should endWith ("world")
string should include ("seven")
"howdy" should contain oneOf ('a', 'b', 'c', 'd')

不错。多谢分享。

#1 楼 @seveniruby JUnit5 断言功能还是没有那么多,https://junit.ci.cloudbees.com/job/JUnit5/javadoc/; Assertions Class;AssertJ 我觉得最大的 2 个亮点是流式和支持的模块总类多(比如 DB 的检验)。

不错耶!希望 python 也有这样的神器 o(╯□╰) o

流式更符合测试的需求吧

我们之前自动化都是自己封装,不然会中断流程,主要原因还是颗粒度达不到那么小

前段时间学习 java 写断言测试接口的时候好生痛苦,不过痛过就好了:)

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册