groovy(Spock) 中的测试文件结构

Test file structure in groovy(Spock)

如何在 groovy(Spock) 中测试创建的和预期的文件树? 现在我正在使用 Set,我在其中指定我希望获得的路径并以这种方式收集实际路径:

Set<String> getCreatedFilePaths(String root) {
    Set<String> createFilePaths = new HashSet<>()
    new File(root).eachFileRecurse {
        createFilePaths << it.absolutePath
    }
    return createFilePaths
}

但是测试的可读性不是很好。 在 groovy 中是否可以将预期路径写成树,然后与实际

进行比较

例如,预期:

region:
     usa:
       new_york.json
       california.json
  europe:
       spain.json
       italy.json

而实际会转换成这种树。

不确定是否可以使用内置的递归方法来完成。当然有强大的,但这是您可以使用的标准递归代码:

def path = new File("/Users/me/Downloads")

def printTree(File file, Integer level) {
    println "   " * level + "${file.name}:"
    file.eachFile {
        println "   " * (level + 1) + it.name
    }
    file.eachDir {
        printTree(it, level + 1)
    }
}

printTree(path, 1)

打印您描述的格式

您可以构建自己的解析器或使用 Groovy 的内置 JSON 解析器:

package de.scrum_master.Whosebug

import groovy.json.JsonParserType
import groovy.json.JsonSlurper
import spock.lang.Specification

class FileRecursionTest extends Specification {
  def jsonDirectoryTree = """{
      com : {
        na : {
          tests : [
            MyBaseIT.groovy
          ]
        },
        twg : {
          sample : {
            model : [
              PrimeNumberCalculatorSpec.groovy
            ]
          }
        }
      },
      de : {
        scrum_master : {
          Whosebug : [
            AllowedPasswordsTest.groovy,
            CarTest.groovy,
            FileRecursionTest.groovy,
            {
              foo : [
                LoginIT.groovy,
                LoginModule.groovy,
                LoginPage.groovy,
                LoginValidationPage.groovy,
                User.groovy
              ]
            },
            LuceneTest.groovy
          ],
          testing : [
            GebTestHelper.groovy,
            RestartBrowserIT.groovy,
            SampleGebIT.groovy
          ]
        }
      }
    }"""

  def "Parse directory tree JSON representation"() {
    given:
    def jsonSlurper = new JsonSlurper(type: JsonParserType.LAX)
    def rootDirectory = jsonSlurper.parseText(jsonDirectoryTree)

    expect:
    rootDirectory.de.scrum_master.Whosebug.contains("CarTest.groovy")
    rootDirectory.com.twg.sample.model.contains("PrimeNumberCalculatorSpec.groovy")

    when:
    def fileList = objectGraphToFileList("src/test/groovy", rootDirectory)
    fileList.each { println it }

    then:
    fileList.size() == 14
    fileList.contains("src/test/groovy/de/scrum_master/Whosebug/CarTest.groovy")
    fileList.contains("src/test/groovy/com/twg/sample/model/PrimeNumberCalculatorSpec.groovy")
  }

  List<File> objectGraphToFileList(String directoryPath, Object directoryContent) {
    List<File> files = []
    directoryContent.each {
      switch (it) {
        case String:
          files << directoryPath + "/" + it
          break
        case Map:
          files += objectGraphToFileList(directoryPath, it)
          break
        case Map.Entry:
          files += objectGraphToFileList(directoryPath + "/" + (it as Map.Entry).key, (it as Map.Entry).value)
          break
        default:
          throw new IllegalArgumentException("unexpected directory content value $it")
      }
    }
    files
  }

}

请注意:

  • 我使用了 new JsonSlurper(type: JsonParserType.LAX) 以避免在 JSON 结构中引用每个字符串。如果您的文件名包含空格或其他特殊字符,您将不得不使用类似 "my file name" 的名称。

  • rootDirectory.de.scrum_master.Whosebug.contains("CarTest.groovy") 中,您可以看到如何在 .property 语法中很好地与解析的 JSON 对象图进行交互。喜不喜欢,需要与否。

  • 递归方法 objectGraphToFileList 将解析的对象图转换为文件列表(如果你喜欢一个集合,改变它,但 File.eachFileRecurse(..) 不应该产生任何重复,所以不需要集合。

  • 如果您不喜欢 JSON 中的括号等,您仍然可以构建自己的解析器。

  • 您可能想要添加另一种实用方法来从经过验证的目录结构中创建一个 JSON 类似于给定字符串的字符串,这样您在编写类似测试时的工作量就会减少。

修改回答收集文件树路径,排序不关心文件顺序。

def "check directory structure"() {
    expect:
    String created = getCreatedFilePaths(new File("/tmp/region"))
    String expected = new File("expected.txt").text

    created == expected
}

private String getCreatedFilePaths(File root) {
        List paths = new ArrayList()
        printTree(root, 0, paths)
        return paths.join("\n")
    }

private void printTree(File file, Integer level, List paths) {
        paths << ("\t" * level + "${file.name}:")
        file.listFiles().sort{it.name}.each {
            if (it.isFile()) {
                paths << ("\t" * (level + 1) + it.name)
            }
            if (it.isDirectory()) {
                collectFileTree(it, level + 1, paths)
            }
        }
    }

并且预期文件以这种方式以缩进 (\t) 放入 expected.txt 文件中:

region:
    usa:
        new_york.json
        california.json
    europe:
        spain.json
        italy.json