diff --git a/src/main/scala/eu/neverblink/jelly/cli/util/IoUtil.scala b/src/main/scala/eu/neverblink/jelly/cli/util/IoUtil.scala index c020620..1f7ac3f 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/util/IoUtil.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/util/IoUtil.scala @@ -31,5 +31,5 @@ object IoUtil: val file = File(fileName) val suppFile = file.getParentFile val parentFile = if (suppFile != null) suppFile else File(".") - if !parentFile.canWrite then throw OutputFileCannotBeCreated(fileName) + if !parentFile.canWrite || !file.canWrite then throw OutputFileCannotBeCreated(fileName) FileOutputStream(file, true) diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/RdfFromJellySpec.scala b/src/test/scala/eu/neverblink/jelly/cli/command/RdfFromJellySpec.scala index 762ca2c..7cb96e7 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/command/RdfFromJellySpec.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/command/RdfFromJellySpec.scala @@ -2,38 +2,35 @@ package eu.neverblink.jelly.cli.command import com.google.protobuf.InvalidProtocolBufferException import eu.neverblink.jelly.cli.* - import eu.neverblink.jelly.cli.command.helpers.* import eu.neverblink.jelly.cli.command.rdf.* -import org.apache.jena.riot.RDFLanguages import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec -import java.nio.file.attribute.PosixFilePermissions import java.nio.file.{Files, Paths} +import java.nio.file.attribute.PosixFilePermissions import scala.io.Source import scala.util.Using -class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: +class RdfFromJellySpec extends AnyWordSpec with Matchers with TestFixtureHelper: - protected val dHelper: DataGenHelper = DataGenHelper("testRdfFromJelly") + protected val testCardinality: Integer = 33 "rdf from-jelly command" should { "handle conversion of Jelly to NTriples" when { - "a file to output stream" in { - val jellyFile = dHelper.generateJellyFile(3) - val nQuadString = dHelper.generateNQuadString(3) + "a file to output stream" in withFullJellyFile { j => + val nQuadString = DataGenHelper.generateNQuadString(testCardinality) val (out, err) = - RdfFromJelly.runTestCommand(List("rdf", "from-jelly", jellyFile)) + RdfFromJelly.runTestCommand(List("rdf", "from-jelly", j)) val sortedOut = out.split("\n").map(_.trim).sorted val sortedQuads = nQuadString.split("\n").map(_.trim).sorted sortedOut should contain theSameElementsAs sortedQuads } "input stream to output stream" in { - val input = dHelper.generateJellyInputStream(3) + val input = DataGenHelper.generateJellyInputStream(testCardinality) RdfFromJelly.setStdIn(input) - val nQuadString = dHelper.generateNQuadString(3) + val nQuadString = DataGenHelper.generateNQuadString(testCardinality) val (out, err) = RdfFromJelly.runTestCommand( List("rdf", "from-jelly", "--out-format", RdfFormatOption.NQuads.cliOptions.head), ) @@ -41,29 +38,28 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: val sortedQuads = nQuadString.split("\n").map(_.trim).sorted sortedOut should contain theSameElementsAs sortedQuads } - "a file to file" in { - val jellyFile = dHelper.generateJellyFile(3) - val nQuadString = dHelper.generateNQuadString(3) - val outputFile = dHelper.generateFile(RDFLanguages.NQUADS) - val (out, err) = - RdfFromJelly.runTestCommand( - List("rdf", "from-jelly", jellyFile, "--to", outputFile), - ) - val sortedOut = Using.resource(Source.fromFile(outputFile)) { content => - content.getLines().toList.map(_.trim).sorted + "a file to file" in withFullJellyFile { j => + withEmptyQuadFile { q => + val nQuadString = DataGenHelper.generateNQuadString(testCardinality) + val (out, err) = + RdfFromJelly.runTestCommand( + List("rdf", "from-jelly", j, "--to", q), + ) + val sortedOut = Using.resource(Source.fromFile(q)) { content => + content.getLines().toList.map(_.trim).sorted + } + val sortedQuads = nQuadString.split("\n").map(_.trim).sorted + sortedOut should contain theSameElementsAs sortedQuads + out.length should be(0) } - val sortedQuads = nQuadString.split("\n").map(_.trim).sorted - sortedOut should contain theSameElementsAs sortedQuads - out.length should be(0) } - "an input stream to file" in { - val input = dHelper.generateJellyInputStream(3) + "an input stream to file" in withEmptyQuadFile { q => + val input = DataGenHelper.generateJellyInputStream(testCardinality) RdfFromJelly.setStdIn(input) - val outputFile = dHelper.generateFile(RDFLanguages.NQUADS) - val nQuadString = dHelper.generateNQuadString(3) + val nQuadString = DataGenHelper.generateNQuadString(testCardinality) val (out, err) = - RdfFromJelly.runTestCommand(List("rdf", "from-jelly", "--to", outputFile)) - val sortedOut = Using.resource(Source.fromFile(outputFile)) { content => + RdfFromJelly.runTestCommand(List("rdf", "from-jelly", "--to", q)) + val sortedOut = Using.resource(Source.fromFile(q)) { content => content.getLines().toList.map(_.trim).sorted } val sortedQuads = nQuadString.split("\n").map(_.trim).sorted @@ -72,14 +68,13 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: } } "handle conversion of Jelly binary to text" when { - "a file to output stream" in { - val jellyFile = dHelper.generateJellyFile(3) + "a file to output stream" in withFullJellyFile { j => val (out, err) = RdfFromJelly.runTestCommand( List( "rdf", "from-jelly", - jellyFile, + j, "--out-format", RdfFormatOption.JellyText.cliOptions.head, ), @@ -99,7 +94,7 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: | } |}""".stripMargin out should include(outString) - "rows".r.findAllIn(out).length should be(10) + "rows".r.findAllIn(out).length should be(70) "http://example.org/predicate/".r.findAllIn(out).length should be(1) } } @@ -114,87 +109,87 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: RdfFromJelly.getErrString should include(msg) exception.code should be(1) } - "input file is not accessible" in { - val jellyFile = dHelper.generateJellyFile(3) + "input file is not accessible" in withFullJellyFile { j => val permissions = PosixFilePermissions.fromString("---------") Files.setPosixFilePermissions( - Paths.get(jellyFile), + Paths.get(j), permissions, ) val exception = intercept[ExitException] { - RdfFromJelly.runTestCommand(List("rdf", "from-jelly", jellyFile)) + RdfFromJelly.runTestCommand(List("rdf", "from-jelly", j)) } - val msg = InputFileInaccessible(jellyFile).getMessage + val msg = InputFileInaccessible(j).getMessage RdfFromJelly.getErrString should include(msg) exception.code should be(1) } - "output file cannot be created" in { - val jellyFile = dHelper.generateJellyFile(3) - val unreachableDir = dHelper.makeTestDir() - Paths.get(unreachableDir).toFile.setWritable(false) - val quadFile = dHelper.generateFile() - val exception = - intercept[ExitException] { + "output file cannot be created" in withFullJellyFile { j => + withEmptyQuadFile { q => + Paths.get(q).toFile.setWritable(false) + val exception = + intercept[ExitException] { + + RdfFromJelly.runTestCommand( + List("rdf", "from-jelly", j, "--to", q), + ) + } + val msg = OutputFileCannotBeCreated(q).getMessage + Paths.get(q).toFile.setWritable(true) + RdfFromJelly.getErrString should include(msg) + exception.code should be(1) + + } - RdfFromJelly.runTestCommand( - List("rdf", "from-jelly", jellyFile, "--to", quadFile), - ) - } - val msg = OutputFileCannotBeCreated(quadFile).getMessage - Paths.get(unreachableDir).toFile.setWritable(true) - RdfFromJelly.getErrString should include(msg) - exception.code should be(1) } - "deserializing error occurs" in { - val jellyFile = dHelper.generateJellyFile(3) - val quadFile = dHelper.generateFile() - RdfFromJelly.runTestCommand( - List("rdf", "from-jelly", jellyFile, "--to", quadFile), - ) - val exception = - intercept[ExitException] { - RdfFromJelly.runTestCommand( - List("rdf", "from-jelly", quadFile), - ) - } - val msg = InvalidJellyFile(new InvalidProtocolBufferException("")).getMessage - val errContent = RdfFromJelly.getErrString - errContent should include(msg) - errContent should include("Run with --debug to see the complete stack trace.") - exception.code should be(1) + "deserializing error occurs" in withFullJellyFile { j => + withEmptyQuadFile { q => + RdfFromJelly.runTestCommand( + List("rdf", "from-jelly", j, "--to", q), + ) + val exception = + intercept[ExitException] { + RdfFromJelly.runTestCommand( + List("rdf", "from-jelly", q), + ) + } + val msg = InvalidJellyFile(new InvalidProtocolBufferException("")).getMessage + val errContent = RdfFromJelly.getErrString + errContent should include(msg) + errContent should include("Run with --debug to see the complete stack trace.") + exception.code should be(1) + } } - "parsing error occurs with debug set" in { - val jellyFile = dHelper.generateJellyFile(3) - val quadFile = dHelper.generateFile() - RdfFromJelly.runTestCommand( - List("rdf", "from-jelly", jellyFile, "--to", quadFile), - ) - val exception = - intercept[ExitException] { - RdfFromJelly.runTestCommand( - List("rdf", "from-jelly", quadFile, "--debug"), - ) - } - val msg = InvalidJellyFile(new InvalidProtocolBufferException("")).getMessage - val errContent = RdfFromJelly.getErrString - errContent should include(msg) - errContent should include("eu.neverblink.jelly.cli.InvalidJellyFile") - exception.code should be(1) + "parsing error occurs with debug set" in withFullJellyFile { j => + withEmptyQuadFile { q => + RdfFromJelly.runTestCommand( + List("rdf", "from-jelly", j, "--to", q), + ) + val exception = + intercept[ExitException] { + RdfFromJelly.runTestCommand( + List("rdf", "from-jelly", q, "--debug"), + ) + } + val msg = InvalidJellyFile(new InvalidProtocolBufferException("")).getMessage + val errContent = RdfFromJelly.getErrString + errContent should include(msg) + errContent should include("eu.neverblink.jelly.cli.InvalidJellyFile") + exception.code should be(1) + } } - "invalid output format supplied" in { - val jellyFile = dHelper.generateJellyFile(3) - val quadFile = dHelper.generateFile() - val exception = - intercept[ExitException] { - RdfFromJelly.runTestCommand( - List("rdf", "from-jelly", jellyFile, "--to", quadFile, "--out-format", "invalid"), - ) - } - val msg = InvalidFormatSpecified("invalid", RdfFromJellyPrint.validFormatsString) - RdfFromJelly.getErrString should include(msg.getMessage) - exception.code should be(1) + "invalid output format supplied" in withFullJellyFile { j => + withEmptyQuadFile { q => + val exception = + intercept[ExitException] { + RdfFromJelly.runTestCommand( + List("rdf", "from-jelly", j, "--to", q, "--out-format", "invalid"), + ) + } + val msg = InvalidFormatSpecified("invalid", RdfFromJellyPrint.validFormatsString) + RdfFromJelly.getErrString should include(msg.getMessage) + exception.code should be(1) + } } } } diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/RdfToJellySpec.scala b/src/test/scala/eu/neverblink/jelly/cli/command/RdfToJellySpec.scala index 99a224c..5437ec2 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/command/RdfToJellySpec.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/command/RdfToJellySpec.scala @@ -1,7 +1,7 @@ package eu.neverblink.jelly.cli.command import eu.neverblink.jelly.cli.{ExitException, InvalidFormatSpecified} -import eu.neverblink.jelly.cli.command.helpers.{CleanUpAfterTest, DataGenHelper} +import eu.neverblink.jelly.cli.command.helpers.{DataGenHelper, TestFixtureHelper} import eu.neverblink.jelly.cli.command.rdf.{RdfFormatOption, RdfToJelly, RdfToJellyPrint} import eu.ostrzyciel.jelly.convert.jena.riot.JellyLanguage import org.apache.jena.rdf.model.{Model, ModelFactory} @@ -12,9 +12,9 @@ import org.apache.jena.riot.RDFParser import java.io.{ByteArrayInputStream, FileInputStream, InputStream} import scala.util.Using -class RdfToJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: +class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: - protected val dHelper: DataGenHelper = DataGenHelper("testRdfToJelly") + protected val testCardinality: Integer = 33 def translateJellyBack(inputStream: InputStream): Model = Using(inputStream) { content => @@ -28,31 +28,26 @@ class RdfToJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: "rdf to-jelly command" should { "handle conversion of NTriples to Jelly" when { - "a file to output stream" in { - val nQuadFile = dHelper.generateNQuadFile(3) - val tripleModel = dHelper.generateTripleModel(3) + "a file to output stream" in withFullQuadFile { f => val (out, err) = - RdfToJelly.runTestCommand(List("rdf", "to-jelly", nQuadFile)) + RdfToJelly.runTestCommand(List("rdf", "to-jelly", f)) val newIn = new ByteArrayInputStream(RdfToJelly.getOutBytes) val content = translateJellyBack(newIn) - content.containsAll(tripleModel.listStatements()) + content.containsAll(DataGenHelper.generateTripleModel(testCardinality).listStatements()) } - "a file to file" in { - val nQuadFile = dHelper.generateNQuadFile(3) - val newFile = dHelper.generateFile(JellyLanguage.JELLY) - val tripleModel = dHelper.generateTripleModel(3) - val (out, err) = - RdfToJelly.runTestCommand(List("rdf", "to-jelly", nQuadFile, "--to", newFile)) - val content = translateJellyBack(new FileInputStream(newFile)) - content.containsAll(tripleModel.listStatements()) + "a file to file" in withFullQuadFile { f => + withEmptyJellyFile { j => + val (out, err) = + RdfToJelly.runTestCommand(List("rdf", "to-jelly", f, "--to", j)) + val content = translateJellyBack(new FileInputStream(j)) + content.containsAll(DataGenHelper.generateTripleModel(testCardinality).listStatements()) + } } - "input stream to output stream" in { - val testNumber = 10 - val input = dHelper.generateNQuadInputStream(testNumber) + val input = DataGenHelper.generateNQuadInputStream(testCardinality) RdfToJelly.setStdIn(input) - val tripleModel = dHelper.generateTripleModel(testNumber) + val tripleModel = DataGenHelper.generateTripleModel(testCardinality) val (out, err) = RdfToJelly.runTestCommand( List("rdf", "to-jelly", "--in-format", RdfFormatOption.NQuads.cliOptions.head), ) @@ -60,28 +55,25 @@ class RdfToJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: val content = translateJellyBack(newIn) content.containsAll(tripleModel.listStatements()) } - - "an input stream to file" in { - val testNumber = 23 - val input = dHelper.generateNQuadInputStream(testNumber) + "an input stream to file" in withEmptyJellyFile { j => + val input = DataGenHelper.generateNQuadInputStream(testCardinality) RdfToJelly.setStdIn(input) - val newFile = dHelper.generateFile(JellyLanguage.JELLY) - val tripleModel = dHelper.generateTripleModel(testNumber) - val (out, err) = RdfToJelly.runTestCommand(List("rdf", "to-jelly", "--to", newFile)) - val content = translateJellyBack(new FileInputStream(newFile)) + val tripleModel = DataGenHelper.generateTripleModel(testCardinality) + val (out, err) = RdfToJelly.runTestCommand(List("rdf", "to-jelly", "--to", j)) + val content = translateJellyBack(new FileInputStream(j)) content.containsAll(tripleModel.listStatements()) } } - "throw proper exception" when { - "invalid format is specified" in { - val jellyFile = dHelper.generateNQuadFile(3) - val exception = - intercept[ExitException] { - RdfToJelly.runTestCommand(List("rdf", "to-jelly", jellyFile, "--in-format", "invalid")) - } - val msg = InvalidFormatSpecified("invalid", RdfToJellyPrint.validFormatsString) - RdfToJelly.getErrString should include(msg.getMessage) - exception.code should be(1) - } + } + "throw proper exception" when { + "invalid format is specified" in withFullQuadFile { f => + val exception = + intercept[ExitException] { + RdfToJelly.runTestCommand(List("rdf", "to-jelly", f, "--in-format", "invalid")) + } + val msg = InvalidFormatSpecified("invalid", RdfToJellyPrint.validFormatsString) + RdfToJelly.getErrString should include(msg.getMessage) + exception.code should be(1) } + } diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/CleanUpAfterTest.scala b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/CleanUpAfterTest.scala deleted file mode 100644 index a328ead..0000000 --- a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/CleanUpAfterTest.scala +++ /dev/null @@ -1,14 +0,0 @@ -package eu.neverblink.jelly.cli.command.helpers - -import org.scalatest.{BeforeAndAfterEach, BeforeAndAfterAll} -import org.scalatest.wordspec.AnyWordSpec - -trait CleanUpAfterTest extends BeforeAndAfterEach, BeforeAndAfterAll { - this: AnyWordSpec => - - protected val dHelper: DataGenHelper - - override def afterAll(): Unit = { - dHelper.cleanUpFiles() - } -} diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/DataGenHelper.scala b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/DataGenHelper.scala index f6f7436..4e02b70 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/DataGenHelper.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/DataGenHelper.scala @@ -2,17 +2,13 @@ package eu.neverblink.jelly.cli.command.helpers import eu.ostrzyciel.jelly.convert.jena.riot.JellyLanguage import org.apache.jena.rdf.model.{Model, ModelFactory, ResourceFactory} -import org.apache.jena.riot.{Lang, RDFDataMgr, RDFLanguages} +import org.apache.jena.riot.{RDFDataMgr, RDFLanguages} -import java.io.{ByteArrayInputStream, ByteArrayOutputStream, FileOutputStream} -import java.nio.file.{Files, Paths} -import scala.collection.mutable.ListBuffer -import scala.util.Using +import java.io.{ByteArrayInputStream, ByteArrayOutputStream} /** This class will be used to generate test data */ -class DataGenHelper(testDir: String = "test"): - private val outputFiles: ListBuffer[String] = ListBuffer[String]() +object DataGenHelper: /** This method generates a triple model with nTriples * @param nTriples @@ -34,21 +30,6 @@ class DataGenHelper(testDir: String = "test"): } model - /** This method generates a Jelly file with nTriples - * @param nTriples - * number of triples to generate - * @return - * String - */ - def generateJellyFile(nTriples: Int): String = - val model = generateTripleModel(nTriples) - val newFile = generateFile(JellyLanguage.JELLY) - // TODO: Add configurable generation for different variants of Jelly (small strict etc) - Using.resource(FileOutputStream(newFile)) { file => - RDFDataMgr.write(file, model, JellyLanguage.JELLY) - } - newFile - /** This method generates a Jelly byte array * * @param nTriples @@ -62,20 +43,6 @@ class DataGenHelper(testDir: String = "test"): RDFDataMgr.write(outputStream, model, JellyLanguage.JELLY) outputStream.toByteArray - /** This method generates a NQuad file with nTriples - * @param nTriples - * number of triples to generate - * @return - * String - */ - def generateNQuadFile(nTriples: Int): String = - val model = generateTripleModel(nTriples) - val newFile = generateFile(RDFLanguages.NQUADS) - Using.resource(FileOutputStream(newFile)) { file => - RDFDataMgr.write(file, model, RDFLanguages.NQUADS) - } - newFile - /** This method generates a Jelly byte input stream with nTriples * @param nTriples * number of triples to generate @@ -112,22 +79,3 @@ class DataGenHelper(testDir: String = "test"): RDFDataMgr.write(outputStream, model, RDFLanguages.NQUADS) val nQuadStream = new ByteArrayInputStream(outputStream.toByteArray) nQuadStream - - /** Make test dir - */ - def makeTestDir(): String = - Files.createDirectories(Paths.get(testDir)) - testDir - - /** Generates the file for test purposes - */ - def generateFile(format: Lang = RDFLanguages.NQUADS): String = - if !Files.exists(Paths.get(testDir)) then makeTestDir() - val extension = format.getFileExtensions.get(0) - val fileName = s"${testDir}/testOutput${outputFiles.size}.${extension}" - outputFiles += fileName - fileName - - def cleanUpFiles(): Unit = - for file <- outputFiles do Files.deleteIfExists(Paths.get(file)) - Files.deleteIfExists(Paths.get(testDir)) diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/TestFixtureHelper.scala b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/TestFixtureHelper.scala new file mode 100644 index 0000000..1fa1b17 --- /dev/null +++ b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/TestFixtureHelper.scala @@ -0,0 +1,64 @@ +package eu.neverblink.jelly.cli.command.helpers + +import eu.ostrzyciel.jelly.convert.jena.riot.JellyLanguage +import org.apache.jena.riot.{Lang, RDFDataMgr, RDFLanguages} +import org.apache.jena.sys.JenaSystem +import org.scalatest.BeforeAndAfterAll +import org.scalatest.wordspec.AnyWordSpec + +import java.io.FileOutputStream +import java.nio.file.{Files, Path} +import java.util.UUID.randomUUID + +object TestFixtureHelper + +trait TestFixtureHelper extends BeforeAndAfterAll: + this: AnyWordSpec => + + TestFixtureHelper.synchronized { + JenaSystem.init() + } + + private val tmpDir: Path = Files.createTempDirectory("jelly-cli") + + /** The number of triples to generate for the tests + */ + protected val testCardinality: Integer + + private def getFileExtension(format: Lang = RDFLanguages.NQUADS): String = + format.getFileExtensions.get(0) + + def withFullQuadFile(testCode: (String) => Any): Unit = + val extension = getFileExtension(RDFLanguages.NQUADS) + val tempFile = Files.createTempFile(tmpDir, randomUUID.toString, extension) + val model = DataGenHelper.generateTripleModel(testCardinality) + RDFDataMgr.write(new FileOutputStream(tempFile.toFile), model, RDFLanguages.NQUADS) + try { + testCode(tempFile.toString) + } finally { tempFile.toFile.delete() } + + def withEmptyJellyFile(testCode: (String) => Any): Unit = + val extension = getFileExtension(JellyLanguage.JELLY) + val tempFile = Files.createTempFile(tmpDir, randomUUID.toString, extension) + try { + testCode(tempFile.toString) + } finally { tempFile.toFile.delete() } + + def withFullJellyFile(testCode: (String) => Any): Unit = + val extension = getFileExtension(JellyLanguage.JELLY) + val tempFile = Files.createTempFile(tmpDir, randomUUID.toString, extension) + val model = DataGenHelper.generateTripleModel(testCardinality) + RDFDataMgr.write(new FileOutputStream(tempFile.toFile), model, JellyLanguage.JELLY) + try { + testCode(tempFile.toString) + } finally { tempFile.toFile.delete() } + + def withEmptyQuadFile(testCode: (String) => Any): Unit = + val extension = getFileExtension(RDFLanguages.NQUADS) + val tempFile = Files.createTempFile(tmpDir, randomUUID.toString, extension) + try { + testCode(tempFile.toString) + } finally { tempFile.toFile.delete() } + + override def afterAll(): Unit = + Files.deleteIfExists(tmpDir)