【问题标题】:How to recognize test classes in a project如何识别项目中的测试类
【发布时间】:2016-03-09 16:58:28
【问题描述】:

我正在使用以下代码来识别项目中的测试类,整个想法是找到测试类并将测试代码的数量与生产代码进行比较!这是我的一段代码,它负责查找测试类并计算行数:

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

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

            System.out.println("File:" + f.getName());
            countFiles++;

            Scanner testScanner = new Scanner(f);
            while (testScanner.hasNextLine()) {

                String test = testScanner.nextLine();
                if (test.contains("org.junit") || test.contains("org.mockito") || test.contains("org.easymock")) {
                    hasTestLines = true;
                    //      break;
                }
                testCounter++;
            }

但是在几个项目上运行代码后,我意识到找到包含UnitEasyMockMockito 的测试类的想法并不是找到测试类的最佳实践,因为几个项目使用自己的测试方法!所以问题是有比我更好的方法来定义测试类吗?

谢谢

【问题讨论】:

  • 如果您要寻找自定义测试类,我可以在其中命名任何我想要的类和函数,那么您可能不走运。话虽这么说,通常人们会将他们的函数命名为“test ...”,因此您可以计算名称中包含“test”的函数的数量。我看到的另一个问题是您的代码会识别在 cmets 中有 org.junit 的文件。
  • 所以您认为应该手动研究和计算自定义测试类?
  • 这是一个 Maven 项目吗?你可以使用 Maven 插件吗? Sonar plugin 代码覆盖率?
  • 除非您知道用于这些测试类的模式。例如,我可以用函数tInttFloat 命名一个类TClasses。对于此类,名称前面的“t”表示测试。但要提前知道这一点并不容易。除非这是您正在分析的所有(或部分)项目的标准。

标签: java


【解决方案1】:

你能不能只是 load classes 并将它们作为参数传递 像

这样的测试运行者

org.junit.runner.JUnitCore.runClasses(TestClass1.class, ...);

并使用测试运行器的输出。

现在测试运行器在一个类中搜索测试方法。

如果类不包含任何内容,它将不会成功,因此 一个生产班。 (假设所有测试类都成功!)

在我的实现中,我只计算类的数量,但你 可以扩展它来计算行数,然后进行比较。

这里是实现:

 public void compareTestAndProduction () {

    // pattern to split the name of class from it's extension
    String pattern = "(.*)(?=.class)";

    // package to proove
    String packageName = "stackoverflow.test";

    // relative path of package
    String packagePath = "stackoverflow/test";

    // counter for number of test classes
    int testCounter = 0;

   // counter for number of production classes
    int codeCounter = 0;

    // classloader for test and production classes
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

    try {
        // load package resources to file
        Enumeration enumeration = classLoader.getResources(packagePath);
        URL url = (URL) enumeration.nextElement();
        File classFiles = new File(url.getFile());

        // read all subfiles in File
        // which contains the package dir and all classes
        for (File classFile : classFiles.listFiles()) {
            String classNameWithExtension = classFile.getName();
            // proov if name of class is no directory
            if (classNameWithExtension.endsWith(".class")) {
                // extend the class with the package name
                // and get rid of the extension .class
                String className = packageName + "." + classNameWithExtension.split("[.]")[0];
                
                // load class
                Class c = classLoader.loadClass(className);
                
                // run the class with a test runnner
                // which will search class for test methods
                Result result = org.junit.runner.JUnitCore.runClasses(c.newInstance().getClass());

                // if testmethods found
                // and they are successful
                // raise testcounter
                if(result.wasSuccessful())
                    testCounter++;
                else codeCounter++;


            }
        }
        System.out.println("Test classes:\n" + testCounter);
        System.out.println("Production classes:\n" + codeCounter);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

就我而言

测试类:

1

生产类:

2

【讨论】:

  • 我真的不明白你的想法,你能再描述一下吗?谢谢
  • 这个想法是通过测试运行器而不是通过出现一些关键字(如 test、mockito ....)来查找测试方法/类,因为测试运行器知道如何去做。
【解决方案2】:

在 java 中,生产代码通常保存在 src/main/java 中,测试代码保存在 src/test/java 中

【讨论】:

  • 感谢您的回答!事实上,我正在考虑将我的逻辑更改为您的逻辑,但我不确定这是否适用于所有情况?
  • 几乎在所有情况下都遵循它,我没有看到任何具有任何其他目录结构的项目。像 gradle/maven 这样的项目构建工具定义了与默认相同的目录结构
【解决方案3】:

不确定您想要实现什么,但应将测试代码和实际代码分开。您可以使用 emma、cobertura、sonar 等插件进行代码覆盖。

但是,如果您正在做一些练习,请查看以下选项。

测试类可以有一个测试前缀或后缀。

测试类实现/扩展一个接口,例如测试用例。

测试类在顶部使用注释,例如@TestCase。

具有带注释的方法的测试类,例如@Test。

【讨论】:

  • 我实际上是在做研究,我应该分析足够数量的项目,看看这些项目有多少测试代码与生成代码相比,收集数据后我会尝试提出建议以供测试人员和开发人员参考。我的研究将尝试回答一个问题,例如,一个包含 5 个开发人员编写的 10K 行代码的项目应该编写多少测试代码?但是关于您的答案,如果生产类在评论中包含 @Test 那么该类将被视为测试类!
  • 为了您的研究,请使用我建议的工具,它会告诉您一个项目的代码覆盖率。声纳会告诉你行数和百分比。您无需编写代码即可发现这一点,因为您的研究不是如何开发代码覆盖工具。
  • 它会告诉你有多少条测试线吗?您可能已经知道,100% 的覆盖率并不能保证程序没有错误,所以我对覆盖率部分并不感兴趣,我肯定会考虑它,但这不是我首先要看的!你觉得我说的有道理吗?随意讨论和写下你的想法,因为我真的很喜欢听别人的想法和想法!谢谢
  • 那是正确的,没有办法找出来。如果一个项目具有良好的覆盖率,那么其质量良好的机会就很高。
【解决方案4】:

只要您和您的合作者在制作自定义测试类的方式上保持一致,即,如果您都将测试类命名为 SomeClassTest 或 TestSomeClass,或者您甚至可能使用静态方法进行测试。但只要你保持一致,你只需要在这个例子中寻找标题中的“测试”这个词。或者如果你使用静态方法,可能有点棘手。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    • 2014-12-13
    • 2019-06-03
    • 1970-01-01
    相关资源
    最近更新 更多