手机端网站怎么做排名,北京网页制作设计企业,服装定制工作室,蝉知使用WordPress模板第一次偶然发现JUnit Rule批注时#xff0c;我对此概念有些恼火。 在测试用例中拥有一个公共领域似乎有些奇怪#xff0c;因此我不愿意定期使用它。 但是一段时间后#xff0c;我习惯了这一点#xff0c;事实证明#xff0c;规则可以通过多种方式简化编写测试的过程。 这篇… 第一次偶然发现JUnit Rule批注时我对此概念有些恼火。 在测试用例中拥有一个公共领域似乎有些奇怪因此我不愿意定期使用它。 但是一段时间后我习惯了这一点事实证明规则可以通过多种方式简化编写测试的过程。 这篇文章简要介绍了该概念并简要列举了一些规则的优点。 什么是JUnit规则 让我们从一个现成的JUnit规则开始。 TemporaryFolder是一个测试帮助程序可用于为临时内容1创建位于文件系统目录下的文件和文件夹。 TemporaryFolder的有趣之处在于它保证在测试方法完成时删除其文件和文件夹2 。 为了按预期方式工作必须将临时文件夹实例分配给Rule注释字段该字段必须是公共的不是静态的并且是TestRule的子类型 public class MyTest {Rulepublic TemporaryFolder temporaryFolder new TemporaryFolder();Testpublic void testRun() throws IOException {assertTrue( temporaryFolder.newFolder().exists() );}
} 它是如何工作的 规则提供了一种拦截测试方法调用的可能性就像AOP框架一样。 与AspectJ中的周围建议相比您可以在实际测试执行之前和/或之后做一些有用的事情3 。 尽管这听起来很复杂但是却很容易实现。 规则定义的API部分必须实现TestRule。 此接口称为apply的唯一方法返回Statement 。 Statement s表示简单地说在JUnit运行时中的测试而Statement#evaluate()执行它们。 现在基本思想是提供Statement包装扩展该包装可以通过覆盖Statement#evaluate()来进行实际贡献 public class MyRule implements TestRule {Overridepublic Statement apply( Statement base, Description description ) {return new MyStatement( base );}
}public class MyStatement extends Statement {private final Statement base;public MyStatement( Statement base ) {this.base base;}Overridepublic void evaluate() throws Throwable {System.out.println( before );try {base.evaluate();} finally {System.out.println( after );}}
} MyStatement作为包装器实现在MyRule#apply(Statement,Destination)使用该包装器包装作为参数给出的原始语句。 很容易看出包装程序覆盖了Statement#evaluate()在实际测试4之前和之后做一些事情。 下一个代码片段显示如何与上面的TemporaryFolder完全一样地使用MyRule public class MyTest {Rulepublic MyRule myRule new MyRule();Testpublic void testRun() {System.out.println( during );}
} 启动测试用例将导致以下控制台输出这证明我们的示例规则可以按预期工作。 测试执行被我们的规则拦截和修改以在测试的“期间”前后打印“之前”和“之后” before
during
after 现在已经了解了基础知识下面让我们看一下您可以使用规则执行的更有用的事情。 测试治具 从相应的维基百科部分引用的“测试装置”是运行测试并期望获得特定结果所必须具备的所有条件。 通常通过处理单元测试框架的setUp()和tearDown()事件来创建固定装置。 使用JUnit这通常看起来像这样 public class MyTest {private MyFixture myFixture;Testpublic void testRun1() {myFixture.configure1();// do some testing here}Testpublic void testRun2() {myFixture.configure2();// do some testing here}Beforepublic void setUp() {myFixture new MyFixture();}Afterpublic void tearDown() {myFixture.dispose();}
} 考虑您在许多测试中以上面显示的方式使用特定的夹具。 在那种情况下最好摆脱setUp()和tearDown()方法。 鉴于以上各节我们现在知道可以通过更改MyFixture来实现TestRule来完成。 适当的Statement实现必须确保它调用MyFixture#dispose()并且看起来可能像这样 public class MyFixtureStatement extends Statement {private final Statement base;private final MyFixture fixture;public MyFixtureStatement( Statement base, MyFixture fixture ) {this.base base;this.fixture fixture;}Overridepublic void evaluate() throws Throwable {try {base.evaluate();} finally {fixture.dispose();}}
} 有了这个上面的测试可以重写为 public class MyTest {Rulepublic MyFixture myFixture new MyFixture();Testpublic void testRun1() {myFixture.configure1();// do some testing here}Testpublic void testRun2() {myFixture.configure2();// do some testing here}
} 在很多情况下我开始欣赏使用规则编写测试的更为紧凑的形式但是可以肯定的是这也是一个品味问题以及您认为更适合阅读的内容5 。 带有方法注释的夹具配置 到目前为止我已默默地忽略了TestRule#apply(Statement,Description)的Description参数。 通常 Description描述了将要运行或已经运行的测试。 但它也允许访问有关底层java方法的一些反射信息。 除其他外有可能读取这种方法附带的注释。 这使我们能够将规则与方法注释结合起来以方便配置TestRule 。 考虑以下注释类型 Retention(RetentionPolicy.RUNTIME)
Target({ElementType.METHOD})
public interface Configuration {String value();
} 与MyFixture#apply(Statement,Destination)中的以下代码段结合使用该代码读取注释为特定测试方法的配置值… Configuration annotation description.getAnnotation( Configuration.class );
String value annotation.value();
// do something useful with value …上面演示MyFixture规则用法的MyFixture可以重写为 public class MyTest {Rulepublic MyFixture myFixture new MyFixture();TestConfiguration( value configuration1 )public void testRun1() {// do some testing here}TestConfiguration( value configuration2 )public void testRun2() {// do some testing here}
} 当然由于注释仅允许Enum Class es或String文字作为参数因此后一种方法存在局限性。 但是在某些用例中这已经足够了。 restfuse库提供了一个很好的示例该示例将规则与方法注释结合使用。 如果您对现实世界的示例感兴趣则应查看Destination规则6的库实现。 最后剩下的唯一要说的是我很想听听您关于可以用来简化日常测试工作的JUnit规则的其他有用示例的信息 通常由System.getProperty( java.io.tmpdir );返回的目录System.getProperty( java.io.tmpdir ); ↩ 在查看TemporaryFolder的实现时我必须注意它不会检查文件删除是否成功。 这可能是打开的文件句柄的情况下一个薄弱点↩ 值得的是您甚至可以用其他方法代替完整的测试方法↩ 包装语句的委托放入try...finally块中以确保执行测试后的功能即使测试失败。 在这种情况下一个AssertionError会被抛出并且不是在finally块语句都将跳过↩ 你可能注意到TemporaryFolder之初例子也不外乎夹具的使用情况↩ 请注意restfuse的Destination类实现了MethodRule而不是TestRule 。 这篇文章基于最新的JUnit版本其中MethodRule被标记为Deprecated 。 TestRule代替MethodRule 。 但是鉴于此职位的知识仍然应该很容易理解实现↩ 参考来自JCG合作伙伴 Frank Appel的JUnit规则 位于Code Affine博客上。 翻译自: https://www.javacodegeeks.com/2012/11/junit-rules.html