[介面測試]通過Class檔案掃描來統計待測應用的介面數

weixin_34019929發表於2017-07-03

背景:開始一個應用的介面測試開發前,我們首先要搞清楚:待測應用到底有多少介面,同時在後續的維護中我們需要知道:新增了哪些介面、減少了哪些介面,這樣方便進行用例的同步。

怎麼去統計這些介面呢?

第一反應找開發講解了下應用的程式碼和介面的所屬模組後開始人肉統計,但是這樣做無技術含量、重複勞動、冗餘出錯,那有沒有辦法通過工具去掃描介面。

先去百度看看有沒有現成的輪子可以用,沒有找到合適的工具,於是自己開始造輪子。

我們的需求是什麼

需求:統計一個應用下面介面數。
介面是如何定義的?在我負責的應用程式碼中,有2個關鍵flag可以標識介面:

  • 類有註解@WebResource
  • 方法上有註解@ResourceMapping

程式碼

通過ClassLoader去實現介面程式碼統計:

  • 一個簡單的SpringBoot應用:
    • 啟動方法:
@EnableAutoConfiguration
public class Application {

    /**
     * @param args
     * @throws MalformedURLException
     */
    public static void main(String[] args) throws MalformedURLException {
        String dir = "/xxx/target/classes/";

        // 掃描目錄下有哪些class檔案,得到classname的列表
        DirScanner dirScanner = new DirScanner();
        List<File> nameLst = dirScanner.scan(dir);

        List<String> classnameLst = new ArrayList<>();
        for (File classFile : nameLst) {
            String className = classFile.getAbsolutePath().replace(dir, "").replace("/", ".").replace(".class", "");
            classnameLst.add(className);
        }
        
        // 載入class檔案到jvm,掃描介面
        CodeScanner codeScanner = new CodeScanner();
        codeScanner.scan(dir, classnameLst);

    }
}
  • DirScanner原始碼:
    作用:根據傳入的路徑遞迴掃描得到路徑下所有檔案的列表
public class DirScanner {

    /**
     * @return
     */
    public List<File> scan(String dir) {
        ArrayList<File> nameLst = new ArrayList<>();
        File file = new File(dir);

        if (!file.exists()) {
            return nameLst;
        }

        if (!file.isDirectory()) {
            nameLst.add(file);
            return nameLst;
        }

        File[] files = file.listFiles();

        for (File childFile : files) {
            if (childFile.isDirectory()) {
                nameLst.addAll(this.scan(childFile.getAbsolutePath()));
//                System.out.println("0" + childFile.getName());
            } else {
                if (childFile.getName().endsWith(".class")) {
                    nameLst.add(childFile);
//                    System.out.println("1" + childFile.getName());
                } else {
//                    System.out.println("2" + childFile.getName());
                }
            }
        }

        return nameLst;
    }
}
  • CodeScanner原始碼:
    作用:將路徑下的class檔案載入到jvm,然後根據classname列表遍歷掃描每個類的註解,返回符合條件的類-介面
public class CodeScanner {

    Class methodAnnotationClass = ResourceMapping.class;
    Class classAnnotationClass = WebResource.class;

    public void scan(String dir, List<String> classnameLst) throws MalformedURLException {
        ClassLoader systemclassloader = ClassLoader.getSystemClassLoader();
        URLClassLoader classLoader = new URLClassLoader(new URL[]{new URL("file://" + dir)}, systemclassloader);
        for (String className : classnameLst) {
            Class<?> clazz = null;
            try {
                clazz = classLoader.loadClass(className);
            } catch (Exception ex) {
                System.out.println("error classname: " + className);
                continue;
            }

            if (clazz.isAnnotationPresent(classAnnotationClass)) {

                Method[] methods = clazz.getMethods();

                for (Method method : methods) {

                    if (method.isAnnotationPresent(methodAnnotationClass)) {
                        System.out.println(className + " | " + method.getName() + " | " + ((ResourceMapping) method.getAnnotation(methodAnnotationClass)).value() + " | ");
                    }
                }

            }
        }
    }
}
  • 注意事項(實際除錯中踩的坑):
    1.URLClassLoader初始化時傳入的URL必須是包路徑的上一層目錄(例如:/xxx/target/classes),然後loadClass時必須要傳入類的全名(package.classname),否則在呼叫loadClass時會報錯:ClassDefNotFoundException,具體原因可以百度“URLClassLoader載入類的路徑”相關說明。
    2.在掃描工具的pom中需要加入被掃描應用的依賴,否則也會報錯:ClassDefNotFoundException,這是因為loadClass時會去執行class檔案的import語句,如果import的類沒有引入,就會報錯。
    3.如果被掃描應用是多模組的應用,模組間有相互依賴,建議將應用的各個模組install到本地倉庫,執行以下命令即可:
mvn clean install -Dmaven.skip.test=true
  • 工具後續如何優化:
    1.將介面的匹配規則提取出來,作為使用者定義/引數傳入。
    2.程式碼中硬編碼需要優化,轉為可配置引數。

  • 掃描結果:


    4383604-0c69018a750a2929.png

    拷貝到Excel簡單處理下就能得到各個類的介面數量。

  • 相比人肉統計的好處在於:
    1.可以反覆統計,後續待測應用有新增/刪除介面,掃描一把和歷史結果對比下就得到結果了
    2.速度快,比人肉統計準確

相關文章