JUnit扩展:引入新注解Annotation

发表于:2015-4-16 12:42

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:大卡    来源:51Testing软件测试网原创

分享:
  这样就可以通过BlockJunit4ClassRunner直接调用:
public class EntryToRunCases
{
public static void main(String... args)
{
if(args != null)
{
System.out.println("Parameters: " + args[0]);
Filter customeFilter = new FilterCollections(args[0]);
EntryToRunCases instance = new EntryToRunCases();
instance.runTestCases(customeFilter);
}
else
{
System.out.println("No parameters were input!");
}
}
protected void runTestCases(Filter aFilter)
{
BlockJUnit4ClassRunner aRunner = null;
try
{
try
{
aRunner = new BlockJUnit4ClassRunner(JunitTest.class);
}
catch(InitializationError e)
{
System.out.print(e.getMessage());
}
aRunner.filter(aFilter);
aRunner.run(new RunNotifier());
}
catch(NoTestsRemainException e)
{
System.out.print(e.getMessage());
}
}
}
  这种方法要比上面IBM的实现,简单很多,不需要包装一些不必要的类了。
  但是我们仍然发现它还有两个不方便的地方:
  要想跑哪些测试文件,必须把相应的测试Class,一条条加进来,这是JUnit固有的缺陷,Categories就是解决这个问题,但是它不识别我们自定义的注解
  Case是通过Java Application Main方法来发起运行的,Eclipse IDE 的Junit 插件并不识别这种用法,所有我们没法在Eclipse的Junit窗口查看结果,只能通过Console打印出书出结果,这样可读性就差了很多
  优化,更佳的解决方法
  第一个问题很好解决,我们只要自己写方法来查找项目下的所有.java文件,匹配包含org.junit.Test.class注解的测试类就可以了,那第二个问题呢?
  仔细思考我们的需求,我们会发现,我们并不想改变JUnit的Case执行能力,我们期望的只是希望JUnit能够只运行我们希望让它跑的Case. 而JUnit的Categories实现的就是这种功能。Categories继承自Suite类,我们看他的构造函数:
  public Categories(Class<?> klass, RunnerBuilder builder)
  throws InitializationError {
  super(klass, builder);
  try {
  filter(new CategoryFilter(getIncludedCategory(klass),
  getExcludedCategory(klass)));
  } catch (NoTestsRemainException e) {
  throw new InitializationError(e);
  }
  assertNoCategorizedDescendentsOfUncategorizeableParents(getDescription());
  }
  实际上就是把自定义的CategoryFilter传递给ParentRunner的filter方法,跟上面的方式,异曲同工。
  Categories不识别我们的注解,那么我们是不是可以仿照它,做自己的Categories类呢?如下:
  1。 首先定义使用自定义Categories的参数:
  @Retention(RetentionPolicy.RUNTIME)
  public @interface IncludeSprint
  {
  String value();
  /*
  * This annotation will determine whether we want to run case without Sprint annotation or not
  * If not set, it is false by default
  */
  boolean isOnly() default false;
  }
  @Retention(RetentionPolicy.RUNTIME)
  public @interface IncludeUserStory
  {
  String value();
  }
  @Retention(RetentionPolicy.RUNTIME)
  public @interface IncludeDefect
  {
  String value();
  }
  2。然后就可以在构造函数里针对它做处理:
  /**
  * Used by JUnit
  */
  public AnnotationClasspathSuite(Class<?> suiteClass, RunnerBuilder builder) throws InitializationError
  {
  super(builder, suiteClass, getTestclasses(new ClasspathClassesFinder(getClasspathProperty(suiteClass), new ClassChecker(
  getSuiteType(suiteClass))).find()));
  try
  {
  filter(new AnnotationsFilter(getIncludedSprint(suiteClass), getIncludedUserStory(suiteClass), getIncludedDefect(suiteClass),
  IsOnlyRunCaseWithSprintAnnotation(suiteClass)));
  }
  catch(NoTestsRemainException e)
  {
  throw new InitializationError(e);
  }
  assertNoCategorizedDescendentsOfUncategorizeableParents(getDescription());
  }
  这样做出的自定义Suite Runner在使用上就非常方便了,比如:
  @RunWith(AnnotationClasspathSuite.class)
  @IncludeSprint(value = "15.3", isOnly = true)
  public class TestRunner
  {
  }
  这样就可以明确的表明,我们只想跑Spring15.3的Case。并且结果也能在Eclipse IDE里完美展示:
  总结
  通过上面的实现,我们就能更细粒度的规划我们的case,也能按需灵活的运行自动化测试用例。
33/3<123
重磅发布,2022软件测试行业现状调查报告~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2023
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号