zoukankan      html  css  js  c++  java
  • [转]Hamcrest指南

    介绍

    Hamcrest是一个书写匹配器对象时允许直接定义匹配规则的框架.有大量的匹配器是侵入式的,例如UI验证或者数据过滤,但是匹配对象在书写灵活的测试是最常用.本教程将告诉你如何使用Hamcrest进行单元测试.

    我的第一个Hamcrest测试

    我们将开始写一个非常简单的JUnit 3测试,但是替换使用JUnit的assertEquals方法,我们使用Hamcrest的assertThat架构和一套标准的匹配器 ,我们需要静态导入它们:

    import static org.hamcrest.MatcherAssert.assertThat;  
    import static org.hamcrest.Matchers.*;
    import junit.framework.TestCase;




    public class BiscuitTest extends TestCase {
    public void testEquals() {
    Biscuit theBiscuit = new Biscuit("Ginger");
    Biscuit myBiscuit = new Biscuit("Ginger");
    assertThat(theBiscuit, equalTo(myBiscuit));
    }
    }

    assertThat方法是一种风格化的句子进行测试断言.在这里例子中,断言问题是第一个方法参数biscuit对象.第二个方法参数是一个Biscuit对象的匹配器.在这是一个使用对象的equals方法检查一个对象等于另一个对象的匹配器.测试前Biscuit类定义了一个equals方法.

    如果你在你的测试中有一个以上的测试,你可以在断言中为你的测试值包含一个标识符:

    assertThat("chocolate chips", theBiscuit.getChocolateChipCount(), equalTo(10));  
    assertThat("hazelnuts", theBiscuit.getHazelnutCount(), equalTo(3));

    其他测试框架

    Hamcrest从一开始就设计结合不同的单元测试框架.例如,Hamcrest可以使用JUnit3和4TestNG.(详细查看完整Hamcrest发布中的例子).在一个现有的测试套件中迁移到使用Hamcrest风格的断言是很容易的,因为其他断言风格可以和Hamcrest的共存.

    通过使用从mock Objects框架概念匹配器到Hamcrest匹配器桥接适配器Hamcrest也可以在mock objects框架中.例如,JMock 1系统规定是Hamcrest风格.Hamcrest提供了一个JMock 1适配器来允许你在JMock 1测试中使用Hamcrest匹配器.JMock 2不需要这样一个适配器层,因为它被设计使用Hamcrest作为一个匹配库.Hamcrest还提供了EasyMock 2适配器.同样,详细查看Hamcrest例子.

    常用匹配器漫游

    Hamcrest带有一个有用的匹配器库.以下是一些最重要的.

    • 核心
      • anything - 总是匹配,如果你不关心测试下的对象是什么是有用的
      • describedAs - 添加一个定制的失败表述装饰器
      • is - 改进可读性装饰器 - 见下 “Sugar”
    • 逻辑
      • allOf - 如果所有匹配器都匹配才匹配, short circuits (很难懂的一个词,意译是短路,感觉不对,就没有翻译)(像 Java &&)
      • anyOf - 如果任何匹配器匹配就匹配, short circuits (像 Java ||)
      • not - 如果包装的匹配器不匹配器时匹配,反之亦然
    • 对象
      • equalTo - 测试对象相等使用Object.equals方法
      • hasToString - 测试Object.toString方法
      • instanceOf, isCompatibleType - 测试类型
      • notNullValue, nullValue - 测试null
      • sameInstance - 测试对象实例
    • Beans
      • hasProperty - 测试JavaBeans属性
    • 集合
      • array - 测试一个数组元素test an array’s elements against an array of matchers
      • hasEntry, hasKey, hasValue - 测试一个Map包含一个实体,键或者值
      • hasItem, hasItems - 测试一个集合包含一个元素
      • hasItemInArray - 测试一个数组包含一个元素
    • 数字
      • closeTo - 测试浮点值接近给定的值
      • greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo - 测试次序
    • 文本
      • equalToIgnoringCase - 测试字符串相等忽略大小写
      • equalToIgnoringWhiteSpace - 测试字符串忽略空白
      • containsString, endsWith, startsWith - 测试字符串匹配

    Sugar(不明白什么意思?没有翻译)

    Hamcrest努力使你的测试尽可能可读.例如,这是一个匹配器,它是一个不在基本匹配器上添加任何附加行为的包装.下面断言都是一样的:

    assertThat(theBiscuit, equalTo(myBiscuit));  assertThat(theBiscuit, is(equalTo(myBiscuit)));  assertThat(theBiscuit, is(myBiscuit));

    最后那种形式允许的,因为is(T value)是重载返回is(equalTo(value)).(这句话不太明白什么意思)

    定制匹配器

    Hamcrest捆绑了很多有用的匹配器,但你可能会发现不时您需要创建自己的来满足您的测试需求.这通常发生在你找到一个片段的代码,测试相同的性能一遍又一遍(在不同的测试),以及您想要的片段捆绑成一个单一的断言。通过编写自己的匹配器您将去除重复代码,使您的测试更具可读性!

    让我们写我们自己的匹配器测试如果一个double值有NaN值(不是一个数字),这是我们想要写的测试:

    public void testSquareRootOfMinusOneIsNotANumber() {    assertThat(Math.sqrt(-1), is(notANumber()));  }

    这是实现:

    package org.hamcrest.examples.tutorial;     import org.hamcrest.Description;  import org.hamcrest.Factory;  import org.hamcrest.Matcher;  import org.hamcrest.TypeSafeMatcher;     public class IsNotANumber extends TypeSafeMatcher {       @Override    public boolean matchesSafely(Double number) {      return number.isNaN();    }       public void describeTo(Description description) {      description.appendText("not a number");    }       @Factory    public static  Matcher notANumber() {      return new IsNotANumber();    }     }

    我们断言关于两个Double值,所以我们知道我们需要一个Matcher.对于我们的匹配器实现来说作为TypeSafeMatcher子类最方便,它为我们转化一个Double.我们需要仅仅实现matchesSafely方法-它仅仅是检查这个Double是否是NaN,和describedTo方法-它是用来在测试失败时产生失败消息.这是一个失败消息如何显示的列子:

    assertThat(1.0, is(notANumber()));

    失败消息

    java.lang.AssertionError:
    Expected: is not a number
    got : <1.0>

    在我们的匹配器中的第三种方法是一个方便的工厂方法.我们静态导入这种方法来在我们的测试中使用这个匹配器:

    import static org.hamcrest.MatcherAssert.assertThat;  import static org.hamcrest.Matchers.*;     import static org.hamcrest.examples.tutorial.IsNotANumber.notANumber;     import junit.framework.TestCase;     public class NumberTest extends TestCase {       public void testSquareRootOfMinusOneIsNotANumber() {      assertThat(Math.sqrt(-1), is(notANumber()));    }  }

    即使notNumber方法每次调用都创建一个新的匹配器,然而你不应该假设这对你的匹配器是仅有的使用方法.因此你应该确保你的匹配器是无状态的,所以一个单例可以在匹配之间被重用.

    Sugar的生成

    如果你创建了多个自定义匹配器必须分别导入它们所有,这会很麻烦.能够将它们组合起来到一个单独类将会是很好的,所以它们可以像Hamcrest匹配器库那样使用一个静态导入.

    <matchers>       <!-- Hamcrest library -->    <factory class="org.hamcrest.core.Is"/>       <!-- Custom extension -->    <factory class="org.hamcrest.examples.tutorial.IsNotANumber"/>     </matchers>

    其次,运行org.hamcrest.generator.config.XmlConfigurator命令行工具配置Hamcrest.这个工具需要XML配置文件,并生成一个单独Java类文件,它包含所有通过XML文件指定的工厂方法.

    // Generated source.  
    package org.hamcrest.examples.tutorial;
    public class Matchers {
    public static org.hamcrest.Matcher is(T param1) {
    return org.hamcrest.core.Is.is(param1);
    }
    public static org.hamcrest.Matcher is(java.lang.Class param1) {
    return org.hamcrest.core.Is.is(param1);
    }
    public static org.hamcrest.Matcher is(org.hamcrest.Matcher param1) {
    return org.hamcrest.core.Is.is(param1);
    }
    public static org.hamcrest.Matcher notANumber() {
    return org.hamcrest.examples.tutorial.IsNotANumber.notANumber();
    }
    }

    最后,我们可以更新我们的测试使用新的匹配器类.

    import static org.hamcrest.MatcherAssert.assertThat;     import static org.hamcrest.examples.tutorial.Matchers.*;     import junit.framework.TestCase;     public class CustomSugarNumberTest extends TestCase {       public void testSquareRootOfMinusOneIsNotANumber() {      assertThat(Math.sqrt(-1), is(notANumber()));    }  }

    请注意我们现在的使用Hamcrest库是从我们自己定制的匹配器类导入的匹配器.

    You can follow any responses to this entry through the RSS 2.0 feed.
    You can leave a response, or trackback from your own site.


    引文来源 Hamcrest指南 | 舞命小丢

    转自:http://littlefermat.blog.163.com/blog/static/597711672009525113625724/

  • 相关阅读:
    网站发布小工具,--让发布变简单一点
    鼠标右键发布文件到远程服务器
    关于跑步耳机的一些思考
    对棋牌游戏平台的一些思考
    复杂业务简单化的一个小技巧
    游戏杂记
    python 杂记
    lua debug
    quick-cocos2d-x 杂记
    Linux 杂记
  • 原文地址:https://www.cnblogs.com/jancco/p/2488969.html
Copyright © 2011-2022 走看看