JAVA 自定义注解在自动化测试中的使用

在 UI 自动化测试中,相信很多人都喜欢用所谓的 PO 模式,其中的 P,也就是 page 的意思,于是乎,在脚本里,或者在其它的 page 里,会要 new 很多的 page 对象,这样很麻烦,前面我们也讲到了注解的使用,很方便,那么我们可不可以用注解来代替这个 new 的过程呢?只有想不到,没有办不到的,因为 springMVC 就是用了这个方式来 IOC,当然我们也可以直接用 springMVC,但这无异于用牛刀来切豆腐,还不如我们自已实现一下,顺便增加一下对注解的使用的认识,代码如下:

1. 先定义一个 LoadPage 的注解:

1
2
3
4
5
6
7
8
9
10
11
12
package com.test.annotation;
 
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 LoadPage {
    String value();
}

 2. 再来实现一下这个注解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.test.annotation;
 
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
 
import org.openqa.selenium.WebDriver;
 
public class LoadAllPage {
     
    public final String basePath = "com.test";
     
    private final String binPath = "bin";
     
    private List<String> allClass = new ArrayList<String>();   
     
    private WebDriver driver;  
     
    public void setDriver(WebDriver driver) {
        this.driver = driver;
    }
 
    public void loadAllPage(){     
        this.listAllFiles(binPath+File.separator+basePath.replace(".","/"));
        this.getPageInstance();
    }
     
    private void listAllFiles(String path){
        path = path.replace("\\", "/");
        File file = new File(path);
        if(file.isFile() && file.getName().endsWith(".class")){
            String filePath = file.getPath().replace("\\", "/");           
            int startIndex = 4;
            int endIndex = filePath.lastIndexOf(".class");
            allClass.add(filePath.substring(startIndex, endIndex).replace("/", "."));              
        }else if(file.isDirectory()){
            File[] files = file.listFiles();
            for (File f : files) {
                this.listAllFiles(f.getPath());
            }
        }
    }
     
    private void getPageInstance(){
        for (String clazz : allClass) {
            try {              
                Class<?> c = Class.forName(clazz);               
                if(c.isAnnotationPresent(LoadPage.class)){
                    LoadPage lp = c.getAnnotation(LoadPage.class);
                    Constructor<?> cons = c.getConstructor(WebDriver.class);                 
                    InitialManger.allInstance.put(lp.value(), cons.newInstance(driver));
                }
            } catch (ClassNotFoundException e) {               
                e.printStackTrace();
            } catch (InstantiationException e) {               
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }  
 
    public static void main(String[] args) {
        LoadAllPage lap = new LoadAllPage();
        lap.loadAllPage(); 
    }
}

 3. 再定义一个 Page 注解:

1
2
3
4
5
6
7
8
9
10
11
12
package com.test.annotation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Page {
    public String name() default "";
}

 4. 同样的,需要实现下 Page 注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.test.annotation;
 
import java.lang.reflect.Field;
import java.util.Iterator;
 
public class AutoPage {
     
    public void setPageAnnotation(){
        Iterator<String> it = InitialManger.allInstance.keySet().iterator();
        while(it.hasNext()){
            String key = it.next();
            try {              
                Class<?> c = InitialManger.allInstance.get(key).getClass();              
                Field[] fields = c.getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    if(field.isAnnotationPresent(Page.class)){
                        field.set(InitialManger.allInstance.get(key), InitialManger.allInstance.get(field.getAnnotation(Page.class).name()));
                    }
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            }
        }      
    }  
     
    public void setTestAnnotation(Object o) {
        try {              
            Class<?> c = o.getClass();               
            Field[] fields = c.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                if(field.isAnnotationPresent(Page.class)){
                    field.set(o, InitialManger.allInstance.get(field.getAnnotation(Page.class).name()));
                }
            }  
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
    }
     
}

 5. 增加一个所有 page 实例化后的对象管理类:

1
2
3
4
5
6
7
8
9
10
package com.test.annotation;
 
import java.util.HashMap;
import java.util.Map;
 
public class InitialManger {
     
    public static Map<String, Object> allInstance = new HashMap<String, Object>();
     
}

 6. 再来初始化一下实现注解类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.test.annotation;
 
import org.openqa.selenium.WebDriver;
 
public class InitialAnnotation {
     
    private WebDriver driver;
     
    public InitialAnnotation(WebDriver driver) {
        this.driver = driver;
    }
 
    public void initialAnnotation(){       
        LoadAllPage lap = new LoadAllPage();
        lap.setDriver(driver);
        lap.loadAllPage();
        AutoPage ap = new AutoPage();
        ap.setPageAnnotation();
    }
 
     
}

 7. 接下来就是使用了:在一个 Page 中加上这个 @LoadPage 注解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.test.page;
 
import org.openqa.selenium.WebDriver;
 
import com.test.annotation.LoadPage;
import com.test.base.Page;
 
@LoadPage("firstPage")
public class FirstPage extends Page{
 
    public FirstPage(WebDriver driver) {
        super(driver);     
    }
     
    public void linkToMobileList(){
        driver.navigate().to("http://www.baidu.com");
    }
 
}

 8. 为了使 @Page 注解在 case 中能用到,所以得在 TestBase 的 @BeforeClass 中添加如下代码:

1
2
3
4
5
6
if(InitialManger.allInstance.isEmpty()){
            InitialAnnotation init = new InitialAnnotation(driver);
            init.initialAnnotation();
        }
        AutoPage ap = new AutoPage();
        ap.setTestAnnotation(this);

 9. 在 CASE 中这样用即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.test.testcases;
 
import java.util.Map;
 
import org.testng.annotations.Test;
 
import com.test.annotation.Page;
import com.test.base.TestBase;
import com.test.page.FirstPage;
 
public class Test2 extends TestBase{
     
    @Page(name="firstPage")
    private FirstPage firstPage;
     
    @Test(dataProvider="providerMethod")
    public void testLogin(Map<String, String> param){
        firstPage.linkToMobileList();
    }
 
}

 整个过程就是这样的,可能有人会说这样也不方便,等等等等,总是有人能接受,有人不能接受的,如果能接受,可以找我共同讨论一下。QQ:408129370