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

Posted

技术标签:

【中文标题】在 groovy (Spock) 中测试文件结构【英文标题】:Test file structure in groovy(Spock) 【发布时间】:2018-08-06 14:42:55 【问题描述】:

如何在 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

而实际会转换成这种树。

【问题讨论】:

【参考方案1】:

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

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)

打印你描述的格式

【讨论】:

我认为 OP 想要解析该结构,而不是创建它。 我想以一种可读的方式比较我的实际文件树和预期的文件树。其实这个想法很好,只需要这个方法返回String,这样的话,我就可以比较我的String了。 modified 你的回答,对我来说看起来又好又简单【参考方案2】:

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

package de.scrum_master.***

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 : 
          *** : [
            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.***.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/***/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.***.contains("CarTest.groovy") 中,您可以看到如何以.property 语法很好地与解析的JSON 对象图进行交互。你可能喜欢与否,需要与否。

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

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

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

【讨论】:

谢谢,这是个好主意,但对我来说,阅读起来有点负担。 我明白了。好处是 JSON 是一种标准格式。但您也可以轻松冲泡自己的咖啡。 ?【参考方案3】:

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

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().sortit.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

【讨论】:

以上是关于在 groovy (Spock) 中测试文件结构的主要内容,如果未能解决你的问题,请参考以下文章

Groovy/Spock 测试导论

Groovy单元测试框架spock数据驱动Demo

大量的 spock 测试导致 eclipse 中的编译时间很长

Spock 不使用 Groovy MetaClass 对待测服务的更改

在Spring Boot项目中使用Spock测试框架

Spock单测利器的写法