2016-02-27 3 views
0

Я создаю программу, которая распознает классы тестов и дает кодеру представление о том, сколько кода теста он написал по сравнению с фактическим исходным кодом. Мой вопрос: как я могу заставить программу распознать тестовый класс, несмотря на тип тестов, которые были использованы? какой главный признак вы можете найти в тестовом классе? Это нотация @Test? Если да, то как с этим справиться?Лучший способ распознать тестовые классы?

Это кусок кода класса, который я сделал, чтобы распознавать тестовые классы:

public void walk(String path) throws FileNotFoundException { 
    int countFiles = 0; 
    File root = new File(path); 
    File[] list = root.listFiles(); 
    if (list == null) { 
     return; 
    } 

    for (File f : list) { 
     if (f.isDirectory()) { 
      walk(f.getAbsolutePath()); 
     } 

     if (f.getName().endsWith(".java")) { 

      System.out.println("File:" + f.getName()); 
       Scanner sc2 = new Scanner(f); 

      while (sc2.hasNextLine()) { 

       count++; 

       String str = sc2.nextLine(); 

       for (int i = 0; i < str.length(); i++) { 
        if(str.equals("@Test")){ 
        System.out.println("this a test clsee!"); 
       } 

Но, к сожалению, моя идея не работает. Так что я могу сделать?

+0

Почему ваша идея не работает? – Idos

+0

Я не знаю, что я не получаю результата, даже если у меня есть несколько классов тестов, либо оператор if помещен неправильно, либо условие не самое лучшее? (Str.equals ("@ Test")); –

+0

* Не знаю * редко бывает хорошим ответом. Пожалуйста, предоставьте [mcve] (http://stackoverflow.com/help/mcve), если вы хотите получить осмысленный ответ на свой вопрос. – Idos

ответ

0
  1. Не используйте str.equals ("@ Test"), используйте str.contains ("@ Test")
  2. Также хорошо, если вы проверяете str.contains ("org.testng"), ул .contains ("org.junit"), str.contains ("org.easymock"), str.contains ("org.mockito") и т. д.

Upd: Например, вместо кода:

Scanner sc2 = new Scanner(f); 

while (sc2.hasNextLine()) { 

    count++; 

    String str = sc2.nextLine(); 

    for (int i = 0; i < str.length(); i++) { 
     if(str.equals("@Test")){ 
     System.out.println("this a test clsee!"); 

Вы должны использовать код:

Scanner sc2 = new Scanner(f); 
    boolean flag = false; 
    while (sc2.hasNextLine() && !flag) { 
     String str = sc2.nextLine(); 
     if(str.contains("@Test")){ 
      flag = true; 
     } 
    } 
    if(flag) { 
     System.out.println("this a test clsee!"); 
    } 
+0

Привет! Ваша идея работает, но есть небольшая проблема, теперь у меня есть небольшая проблема. Поскольку Am использует этот код сейчас, если (str.contains («@ Test»)) { System.out.println («это тестовый класс»); } позволяет сказать, что класс имеет 4 метода тестирования, другими словами, если у вас есть 4 @Test его печать четыре раза! что я могу сделать, чтобы он печатался только один раз? –

+0

Я обновляю свой ответ –

1

Я понимаю, что это не может быть точно ответ, который вы ищете, но позвольте мне дать вам две альтернативные идеи.

  1. Если вы используете maven или gradle в качестве инструмента сборки, вы должны иметь все тестовые классы в папке src/test/java все равно, что делает его легко отличить их от вашего производства кода (расположенный в src/main/java папка). Другие инструменты могут иметь сходные структуры. Если у вас нет возможности рассмотреть возможность переключения.

    После того, как у вас есть тестовый код и свой производительный код в различных папках, вы можете просто сосчитать все *.java файлов в этих папках структур (или написать летучую мышь/Баш/что сценарий, чтобы сделать это для вас).

  2. Поскольку чистый объем тестового кода на самом деле не сказать вам что-нибудь о вашем фактическом test coverage, вы можете искать инструмент, который поможет вам измерить этот охват и сосредоточиться на качестве, а не количества ваших тестов.

    Если вы используете Eclipse, существует, например, EclEmma (возможно, это не единственный, а не самый лучший, но тот, который я использую). Он добавляет новый режим запуска в Eclipse, и затем вы можете начать свои модульные тесты в Покрытие. В этом режиме EclEmma записывает, какие строки вашего производственного кода исполняются при прохождении теста, что дает вам представление о том, какие части вашего кода проверены, а какие нет. Он также вычисляет некоторые статистические данные о проценте линий или филиалов, которые помогут вам определить слабые места.

(Теперь, по крайней мере, быстро адресуйте свой код: теоретически ваш подход должен работать.На практике это похоже на то, что вы должны прочитать сравнение строк в java. Возможно, стоит заменить вашу петлю str.equals("@Test") простым str.contains("@Test").)

+0

Ваш ответ более чем оценен! Но также, имея 100% -ное покрытие для тестирования, не гарантирует бесплатную программу? правильно? :) вот почему я пытаюсь сделать это в своих исследованиях! один из моих исследовательских вопросов - сколько тестового кода достаточно для программы на 5000 строк, написанной двумя разработчиками? , и я попытаюсь найти ответ, проанализировав количество исходных кодов с открытым исходным кодом и тестового кода! Мне очень нравится ваш ответ, не стесняйтесь придумывать больше идей! –

+0

Справа. a) 100% охват теста не говорит вам, что все _комбинации_ ветвей работают правильно, и б) после того, как ваша логика становится более сложной, вероятность увеличивается, если ваш тестовый код либо неверен, либо просто проверяет бессмысленность.Не уверен, что если спрашивать «сколько тестового кода достаточно для строк кода», действительно, эта тема достаточно хорошо освещает. – Marvin

0

Я не уверен, что это то, что вы ищете. После получения имени файла выполните следующие шаги.

Classfile.class.getMethods() 

Итерация методы массив и проверить аннотации класса

method.getAnnotation(Test.class) 

Как было предложено другим это всегда лучше практика не клуб тестовых классов с бизнесом кодом.

Я добавил полный фрагмент кода здесь.

общественного класса ClassFinder {

private static final char PKG_SEPARATOR = '.'; 

private static final char DIR_SEPARATOR = '/'; 

private static final String CLASS_FILE_SUFFIX = ".class"; 

private static final String BAD_PACKAGE_ERROR = "Unable to get resources from path '%s'. Are you sure the package '%s' exists?"; 

public static List<Class<?>> find(String scannedPackage) { 
    String scannedPath = scannedPackage.replace(PKG_SEPARATOR, DIR_SEPARATOR); 
    URL scannedUrl = Thread.currentThread().getContextClassLoader().getResource(scannedPath); 
    if (scannedUrl == null) { 
     throw new IllegalArgumentException(String.format(BAD_PACKAGE_ERROR, scannedPath, scannedPackage)); 
    } 
    File scannedDir = new File(scannedUrl.getFile()); 
    List<Class<?>> classes = new ArrayList<Class<?>>(); 
    for (File file : scannedDir.listFiles()) { 
     classes.addAll(find(file, scannedPackage)); 
    } 
    return classes; 
} 

private static List<Class<?>> find(File file, String scannedPackage) { 
    List<Class<?>> classes = new ArrayList<Class<?>>(); 
    String resource = scannedPackage + PKG_SEPARATOR + file.getName(); 
    if (file.isDirectory()) { 
     for (File child : file.listFiles()) { 
      classes.addAll(find(child, resource)); 
     } 
    } else if (resource.endsWith(CLASS_FILE_SUFFIX)) { 
     int endIndex = resource.length() - CLASS_FILE_SUFFIX.length(); 
     String className = resource.substring(0, endIndex); 
     try { 
      classes.add(Class.forName(className)); 
     } catch (ClassNotFoundException ignore) { 
     } 
    } 
    return classes; 
} 

public static void main(String[] args) { 
    List<Class<?>> classes = ClassFinder.find("com.vijay.junitapp4"); 
    Method[] methods = null; 
    for (Class<?> class1 : classes) { 
     methods = class1.getMethods(); 
     Test test = null; 
     for (int j = 0; j < methods.length; j++) { 
      test = methods[j].getAnnotation(Test.class); 
      if(null != test){ 
       System.out.println("we found a teat case"); 
       break; 
      } 
     } 
    } 
} 

}

+0

Не совсем уверен. Если я получу вашу идею, пожалуйста, опишите больше? –

+0

Имена файлов, которые вы получаете, являются строками, поэтому для преобразования его в файл класса мне нужно использовать Class.forName («<полное имя класса>»). Я предоставляю фрагмент кода, который я прочитал из http://stackoverflow.com/questions/15519626/how-to-get-all-classes-names-in-a-package Спасибо автору. –

Смежные вопросы