Skip to content

Instantly share code, notes, and snippets.

@fanf
Last active December 10, 2015 10:00
Show Gist options
  • Save fanf/ba17c562bb2d1bf191ad to your computer and use it in GitHub Desktop.
Save fanf/ba17c562bb2d1bf191ad to your computer and use it in GitHub Desktop.
Specs2: compare files in two directories, filtering out some line based on regex (for ex when they contains datetime "now", random id, etc)
package test
/**
* Specs2 matcher are wonderful. You're almost sur to find one for your need, whatever the need.
* Mine was to compare the output of an algo writting a directory tree with template filled
* with a reference one. And great! Specs2 has a:
*
* actualDir must haveSameFilesAs(expectedDir)
*
* See: https://etorreborre.github.io/specs2/guide/SPECS2-3.6.6/org.specs2.guide.Matchers.html#optional
* in section "File Content"
*
* But I needed to filter out some line comparison in my file, because they were filled with
* non predictible data (like generated uuid or "System.currentTimeMillis")
*
* So I created a pre-filter for the content matcher which filter out lines read from the
* files in directories based on regex, in both the actual and expected directories.
*
* And it was trivial to do it.
*/
// need an extra import: org.specs2" %% "specs2-matcher-extra" % "3.6.6" % "test"
import org.specs2.matcher.ContentMatchers
import org.specs2.io.FileLinesContent
import org.specs2.mutable.Specification
import org.specs2.text.LinesContent
//other imports..
class CompareDirectoryContentSpec extends Specification with ContentMatchers {
// the regex filter allowing to filter out line of files
case class RegexFileContent(regex: List[String]) extends LinesContent[File] {
val patterns = regex.map(_.r.pattern)
override def lines(f: File): Seq[String] = {
FileLinesContent.lines(f).filter { line => !patterns.exists { _.matcher(line).matches() } }
}
override def name(f: File) = FileLinesContent.name(f)
}
// The matcher which uses the content filter to read files
def ignoreSomeLinesMatcher(regex: List[String]): LinesPairComparisonMatcher[File, File] = {
LinesPairComparisonMatcher[File, File]()(RegexFileContent(regex), RegexFileContent(regex))
}
// some code, initialise things, do write your output
"My generated files in generatedDir" should {
"have exactly the same content that the ones in expectedDir (modulo some lines)" in {
generatedDir must haveSameFilesAs(expectedDir)
//this filter already exists in specs2, if you want to completly ignore files
.withFilter { f => f.getName != "rudder_promises_generated" }
//and here, our content matcher which ignores some lines
.withMatcher(ignoreSomeLinesMatcher(
""".*rudder_node_config_id" string => .*"""
:: """.*string => "/.*/configuration-repository.*"""
:: Nil
))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment