zoukankan      html  css  js  c++  java
  • Junit4.x扩展:运行指定方法

        相信很多道友搞开发的一般都会用到Junit单元测试工具,不知道大家有没有遇到一个这样的问题:

            有的单元测试用例有很多@Test方法,甚至有的方法会执行很长时间,只能空等执行。而实际上我们只需要运行其中的某一些方法就可以了。然后有人会说不是有ingore注解么,可ingore需要为许多的方法添加,当测试方法达到一定数量级的时候,改起来会很烦躁,如果commit到代码服务器上甚至可能会影响别人工作。己所不欲...

        之前有朋友跟我说过TestNG是支持指定执行哪些方法,本人没有亲自去实验,因为公司统一使用Junit,所以没打算在这上面花费学习成本,没有固定测试框架的朋友不妨自己了解一下。下面开始扩展:


    项目下载:

        下载


    实现思路

        1、在正常运行的情况下,Junit被触发会调用org.junit.runners.BlockJUnit4ClassRunner类,加载测试类文件,执行before after childrenInvoker等方法,有兴趣的道友可以自己看下这个类的结构,今天的主角是childrenInvoker方法,这个方法调用了测试类文件的@Test方法并执行,我们要做的就是重写这个方法,根据我们自己的规则选择执行哪些方法。

        2、根据上一条我们要扩展一个R我unner继承自BlockJUnit4ClassRunner,在这里进行参数过滤。

        3、我们可能希望方法可以模糊匹配,也可能希望可以指定某几个固定的写法,所以需要引入一种过滤规则,这里采用正则表达式。过滤规则的传递采用注解,因为我觉得简洁,忘记注解使用的朋友可以点击这里

        4、Junit4开始提供了RunWith注解,以便让用户自定义扩展Runner,我们的实现就是基于它的这个特性。比较有名的应该大家都比较熟悉spring的Junit扩展。


    代码实现:

    1、定义注解

    package com.array7.annotations;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface FilterMethods {
        String[] methods();
    }

    2、定义Runner  

    package com.array7.runner;
    
    import java.util.HashSet;
    import java.util.Set;
    import java.util.regex.Pattern;
    
    import org.junit.runner.notification.RunNotifier;
    import org.junit.runners.BlockJUnit4ClassRunner;
    import org.junit.runners.model.FrameworkMethod;
    import org.junit.runners.model.InitializationError;
    import org.junit.runners.model.Statement;
    
    import com.array7.annotations.FilterMethods;
    
    public class SpecialMethodsRunner extends BlockJUnit4ClassRunner {
        private FilterMethods filter;
        public SpecialMethodsRunner(Class<?> clazz) throws InitializationError {
            super(clazz);
            filter = clazz.getAnnotation(FilterMethods.class);
        }
    
        /**
         * EnterPoint
         */
        @Override
        protected Statement childrenInvoker(final RunNotifier notifier) {
            if (filter == null) {    // keep original runner alone. 
                return super.childrenInvoker(notifier);
            }
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    runMethodsWithFilter(notifier, filter);
                }
            };
        }
        /**
         * Filter the methods could be run.
         * @param notifier
         * @param filterMethods
         */
        private void runMethodsWithFilter(final RunNotifier notifier, final FilterMethods filterMethods) {
            String[] filters = filterMethods.methods();
            if (filters == null || filters.length == 0) {
                throw new IllegalArgumentException(
                        "Wrong parameters!Please check Annotation FilterMthods parameters...");
            }
            
            Set<Pattern> patternSet = new HashSet<Pattern>();
            for (String filter : filters) {
                patternSet.add(Pattern.compile(filter));
            }
            
            for (FrameworkMethod method : getChildren()) {
                for (Pattern pattern : patternSet) {    // loop all patterns
                    if (pattern.matcher(method.getName()).matches()) {    // if matches ...break;
                        runChild(method, notifier);
                        break;
                    }
                }
            }
        }
        
    }


    3、使用实例:

    package junit_ext;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    
    import com.array7.annotations.FilterMethods;
    import com.array7.runner.SpecialMethodsRunner;
    
    @RunWith(SpecialMethodsRunner.class)
    @FilterMethods(methods = { "^.*2$", "^m.*", "ab21"})
    public class DemoTest {
        @Test
        public void m1() {
            System.out.println(123);
        }
    
        @Test
        public void mmm2() {
            System.out.println(456);
        }
    
        @Test
        public void a2() {
            System.out.println(791);
        }
        
        @Test
        public void ab21() {
            System.out.println(7890);
        }
    }

    4、pom.xml依赖

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>

    5、代码经过测试,文章亦可随意转载,唯请保留出处。

  • 相关阅读:
    pandas 之 数据合并
    第一册:lesson sixty five.
    第一册:lesson sixty three。
    C#正则表达式。
    第一册:lesson sixty one.
    C#泛型。
    SQL命令入门。
    C#序列化与反序列化。
    第一册:lesson fifty nine。
    C#文件操作。
  • 原文地址:https://www.cnblogs.com/liushijie/p/4712918.html
Copyright © 2011-2022 走看看