Best Kotest code snippet using io.kotest.matchers.file.matchers.File.shouldBeADirectory
WhenDownloadingAwsDeviceFarmArtifacts.kt
Source:WhenDownloadingAwsDeviceFarmArtifacts.kt  
1package io.github.ricardorlg.devicefarm.tractor.controller2import arrow.core.Either3import io.github.ricardorlg.devicefarm.tractor.model.*4import io.github.ricardorlg.devicefarm.tractor.stubs.*5import io.github.ricardorlg.devicefarm.tractor.tempFolder6import io.github.ricardorlg.devicefarm.tractor.utils.prettyName7import io.kotest.assertions.arrow.core.shouldBeLeft8import io.kotest.assertions.arrow.core.shouldBeRight9import io.kotest.assertions.fail10import io.kotest.assertions.withClue11import io.kotest.core.spec.style.StringSpec12import io.kotest.engine.spec.tempfile13import io.kotest.extensions.system.captureStandardOut14import io.kotest.inspectors.forAll15import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder16import io.kotest.matchers.paths.shouldBeADirectory17import io.kotest.matchers.paths.shouldContainFile18import io.kotest.matchers.paths.shouldContainNFiles19import io.kotest.matchers.paths.shouldNotContainFile20import io.kotest.matchers.should21import io.kotest.matchers.shouldBe22import io.kotest.matchers.string.shouldStartWith23import io.kotest.matchers.throwable.shouldHaveMessage24import io.kotest.matchers.types.shouldBeInstanceOf25import io.kotest.property.Exhaustive26import io.kotest.property.checkAll27import io.kotest.property.exhaustive.collection28import software.amazon.awssdk.services.devicefarm.model.Artifact29import software.amazon.awssdk.services.devicefarm.model.ArtifactType30import software.amazon.awssdk.services.devicefarm.model.Job31import software.amazon.awssdk.services.devicefarm.model.Run32import java.nio.file.AccessDeniedException33import java.nio.file.Paths34import java.nio.file.attribute.PosixFilePermissions35import kotlin.io.path.createDirectory36import kotlin.io.path.listDirectoryEntries37import kotlin.time.Duration38import kotlin.time.Duration.Companion.milliseconds39class WhenDownloadingAwsDeviceFarmArtifacts : StringSpec({40    val logger = MockedDeviceFarmLogging()41    val deviceFarmProjectsHandler = MockedDeviceFarmProjectsHandler()42    val devicePoolsHandler = MockedDeviceFarmDevicePoolsHandler()43    val uploadArtifactsHandler = MockedDeviceFarmUploadArtifactsHandler()44    val runScheduleHandler = MockedDeviceFarmRunsHandler()45    val commonArtifactsHandler = MockedDeviceFarmArtifactsHandler()46    val deviceName = "nexus 3"47    val artifactType = ArtifactType.CUSTOMER_ARTIFACT48    val downloadableTypes = listOf(ArtifactType.CUSTOMER_ARTIFACT, ArtifactType.VIDEO)49    val validTypes =50        ArtifactType.values().filter { it != ArtifactType.UNKNOWN && it != ArtifactType.UNKNOWN_TO_SDK_VERSION }51    "It should use a pretty name when the artifact type is video or customer artifact"{52        checkAll(Exhaustive.collection(ArtifactType.values().asList())) { type ->53            when (type) {54                ArtifactType.VIDEO -> type.prettyName() shouldBe "Recorded video"55                ArtifactType.CUSTOMER_ARTIFACT -> type.prettyName() shouldBe "Test reports"56                else -> type.prettyName() shouldBe type.name57            }58        }59    }60    "It should return a DeviceFarmTractorErrorIllegalArgumentException if the searched artifact type is not supported"{61        checkAll(Exhaustive.collection(INVALID_ARTIFACT_TYPES)) { type ->62            //GIVEN63            val customerArtifact = tempfile("test_downloadable_${type.name.lowercase()}_", ".zip")64            val destinyFolder = tempFolder("testReports")65            val artifact = Artifact66                .builder()67                .arn("arn:test:artifact")68                .name(customerArtifact.nameWithoutExtension)69                .extension(customerArtifact.extension)70                .type(artifactType)71                .url(customerArtifact.toURI().toASCIIString())72                .build()73            //WHEN74            val response = DefaultDeviceFarmTractorController(75                logger,76                deviceFarmProjectsHandler,77                devicePoolsHandler,78                uploadArtifactsHandler,79                runScheduleHandler,80                commonArtifactsHandler81            ).downloadAWSDeviceFarmArtifacts(82                artifacts = listOf(artifact),83                deviceName = deviceName,84                path = destinyFolder,85                artifactType = type86            )87            //THEN88            response.shouldBeLeft() should {89                it.shouldBeInstanceOf<DeviceFarmTractorErrorIllegalArgumentException>()90                it shouldHaveMessage "$type is not supported"91            }92            destinyFolder shouldNotContainFile customerArtifact.name93            destinyFolder shouldContainNFiles 094        }95    }96    "It should download an AWS Device farm artifact of a job execution depending of its type"{97        checkAll(Exhaustive.collection(validTypes)) { type ->98            //GIVEN99            val customerArtifact = tempfile("test_downloadable_${type.name.lowercase()}_", ".zip")100            val destinyFolder = tempFolder("testReports")101            val artifact = Artifact102                .builder()103                .arn("arn:test:artifact")104                .name(customerArtifact.nameWithoutExtension)105                .extension(customerArtifact.extension)106                .type(type)107                .url(customerArtifact.toURI().toASCIIString())108                .build()109            //WHEN110            val response = DefaultDeviceFarmTractorController(111                logger,112                deviceFarmProjectsHandler,113                devicePoolsHandler,114                uploadArtifactsHandler,115                runScheduleHandler,116                commonArtifactsHandler117            ).downloadAWSDeviceFarmArtifacts(118                artifacts = listOf(artifact),119                deviceName = deviceName,120                path = destinyFolder,121                artifactType = type122            )123            //THEN124            response.shouldBeRight()125            destinyFolder shouldContainFile customerArtifact.name126            destinyFolder shouldContainNFiles 1127        }128    }129    "It should log a message when the searched artifact type is not found in the job artifacts"{130        checkAll(Exhaustive.collection(validTypes)) { type ->131            //GIVEN132            val customerArtifact = tempfile("test_downloadable_${type.name.lowercase()}_", ".zip")133            val destinyFolder = tempFolder("testReports")134            val artifact = Artifact135                .builder()136                .arn("arn:test:artifact")137                .name(customerArtifact.nameWithoutExtension)138                .extension(customerArtifact.extension)139                .type(ArtifactType.UNKNOWN)140                .url(customerArtifact.toURI().toASCIIString())141                .build()142            val expectedLoggedMessage = JOB_DOES_NOT_HAVE_ARTIFACT_OF_TYPE.format(143                type.name,144                deviceName145            )146            //WHEN147            val loggedMessage = captureStandardOut {148                DefaultDeviceFarmTractorController(149                    MockedDeviceFarmLogging(true),150                    deviceFarmProjectsHandler,151                    devicePoolsHandler,152                    uploadArtifactsHandler,153                    runScheduleHandler,154                    commonArtifactsHandler155                ).downloadAWSDeviceFarmArtifacts(156                    artifacts = listOf(artifact),157                    deviceName = deviceName,158                    path = destinyFolder,159                    artifactType = type160                ).shouldBeRight()161            }.lines()162                .filter(String::isNotBlank)163                .map(String::trim)164                .last()165            //THEN166            loggedMessage shouldBe expectedLoggedMessage167            destinyFolder shouldNotContainFile customerArtifact.name168            destinyFolder shouldContainNFiles 0169        }170    }171    "It should return an ErrorDownloadingArtifact when there is a problem saving the artifact on disk"{172        //GIVEN173        val onlyReadDestinyFolderPermission = PosixFilePermissions.fromString("r--r--r--")174        val customerArtifact = tempfile("test_downloadable", ".zip")175        val destinyFolder =176            tempFolder("testReports", PosixFilePermissions.asFileAttribute(onlyReadDestinyFolderPermission))177        val artifact = Artifact178            .builder()179            .arn("arn:test:artifact")180            .name(customerArtifact.nameWithoutExtension)181            .extension(customerArtifact.extension)182            .type(ArtifactType.CUSTOMER_ARTIFACT)183            .url(customerArtifact.toURI().toASCIIString())184            .build()185        //WHEN186        val response = DefaultDeviceFarmTractorController(187            logger,188            deviceFarmProjectsHandler,189            devicePoolsHandler,190            uploadArtifactsHandler,191            runScheduleHandler,192            commonArtifactsHandler193        ).downloadAWSDeviceFarmArtifacts(194            artifacts = listOf(artifact),195            deviceName = deviceName,196            path = destinyFolder,197            artifactType = artifactType198        )199        //THEN200        response.shouldBeLeft() should {201            it.shouldBeInstanceOf<ErrorDownloadingArtifact>()202            it.cause.shouldBeInstanceOf<AccessDeniedException>()203        }204    }205    "It should not fail if there is no artifacts to download"{206        //GIVEN207        val customerArtifact = tempfile("test_downloadable", ".zip")208        val destinyFolder = tempFolder("testReports")209        //WHEN210        val response = DefaultDeviceFarmTractorController(211            logger,212            deviceFarmProjectsHandler,213            devicePoolsHandler,214            uploadArtifactsHandler,215            runScheduleHandler,216            commonArtifactsHandler217        ).downloadAWSDeviceFarmArtifacts(218            artifacts = emptyList(),219            deviceName = deviceName,220            path = destinyFolder,221            artifactType = artifactType222        )223        //THEN224        response.shouldBeRight()225        destinyFolder shouldNotContainFile customerArtifact.name226        destinyFolder shouldContainNFiles 0227    }228    "It should download all the test reports and recorded videos associated to the test Run"{229        //GIVEN230        val customerArtifactFile = tempfile("test_downloadable", ".zip")231        val recordedVideoFile = tempfile("test_video", ".mp4")232        val destinyFolder = tempFolder("testReports")233        val run = Run234            .builder()235            .name("test run")236            .arn("arn:test:run")237            .build()238        val jobs = (1..10)239            .map { job ->240                Job241                    .builder()242                    .arn("arn:test:job:$job")243                    .name("test job $job")244                    .device {245                        it.name("Test device $job")246                            .arn("arn:test:device:$job")247                    }.build()248            }249        val customerArtifact = Artifact250            .builder()251            .arn("arn:test:customer_artifact")252            .name(customerArtifactFile.nameWithoutExtension)253            .extension(customerArtifactFile.extension)254            .type(ArtifactType.CUSTOMER_ARTIFACT)255            .url(customerArtifactFile.toURI().toASCIIString())256            .build()257        val recordedVideoArtifact = Artifact258            .builder()259            .arn("arn:test:video_artifact")260            .name(recordedVideoFile.nameWithoutExtension)261            .extension(recordedVideoFile.extension)262            .type(ArtifactType.VIDEO)263            .url(recordedVideoFile.toURI().toASCIIString())264            .build()265        val downloadArtifactsHandler = MockedDeviceFarmArtifactsHandler(266            getArtifactsImpl = { Either.Right(listOf(customerArtifact, recordedVideoArtifact)) }267        )268        val runHandler = MockedDeviceFarmRunsHandler(269            getAssociatedJobsImpl = { Either.Right(jobs) }270        )271        val reportDirectoryPath = Paths.get("test_reports_${run.name().lowercase().replace("\\s".toRegex(), "_")}")272        //WHEN273        DefaultDeviceFarmTractorController(274            logger,275            deviceFarmProjectsHandler,276            devicePoolsHandler,277            uploadArtifactsHandler,278            runHandler,279            downloadArtifactsHandler280        ).downloadAllEvidencesOfTestRun(run, destinyFolder, 0.milliseconds)281        //THEN282        destinyFolder shouldContainFile reportDirectoryPath.toFile().name283        destinyFolder shouldContainNFiles 1284        destinyFolder.resolve(reportDirectoryPath).shouldBeADirectory()285        destinyFolder.resolve(reportDirectoryPath) shouldContainNFiles jobs.size286        destinyFolder.resolve(reportDirectoryPath).listDirectoryEntries().forAll {287            it.shouldBeADirectory()288            it shouldContainFile customerArtifactFile.name289            it shouldContainFile recordedVideoFile.name290            it shouldContainNFiles 2291        }292    }293    "It should log an error message when downloading a recorded video or test report fails"{294        checkAll(Exhaustive.collection(downloadableTypes)) { type ->295            //GIVEN296            val testFile = tempfile("test_downloadable_${type.name.lowercase()}", ".zip")297            val destinyFolder = tempFolder("testReports")298            val run = Run299                .builder()300                .name("test run")301                .arn("arn:test:run")302                .build()303            val job = Job304                .builder()305                .arn("arn:test:job")306                .name("test job")307                .device {308                    it.name(deviceName)309                        .arn("arn:test:device")310                }.build()311            val artifact = Artifact312                .builder()313                .arn("arn:test:artifact")314                .name(testFile.nameWithoutExtension)315                .extension(testFile.extension)316                .type(type)317                .url(testFile.toURI().toASCIIString())318                .build()319            val downloadArtifactsHandler = MockedDeviceFarmArtifactsHandler(320                getArtifactsImpl = { Either.Right(listOf(artifact)) }321            )322            val runHandler = MockedDeviceFarmRunsHandler(323                getAssociatedJobsImpl = { Either.Right(listOf(job)) }324            )325            val reportDirectoryPath =326                Paths.get("test_reports_${run.name().lowercase().replace("\\s".toRegex(), "_")}")327            testFile.setReadable(false)328            //WHEN329            val loggedMessages = captureStandardOut {330                DefaultDeviceFarmTractorController(331                    MockedDeviceFarmLogging(true),332                    deviceFarmProjectsHandler,333                    devicePoolsHandler,334                    uploadArtifactsHandler,335                    runHandler,336                    downloadArtifactsHandler337                ).downloadAllEvidencesOfTestRun(run, destinyFolder, 0.milliseconds)338            }.lineSequence()339                .filter(String::isNotBlank)340                .map(String::trim)341            //THEN342            destinyFolder shouldContainNFiles 1343            destinyFolder shouldContainFile reportDirectoryPath.fileName.toString()344            destinyFolder.resolve(reportDirectoryPath).shouldBeADirectory()345            destinyFolder.resolve(reportDirectoryPath) shouldContainNFiles 0346            withClue("The logged messages should contain an error message related to the error downloading the artifact $type") {347                loggedMessages.any {348                    it.startsWith(349                        "There was an error downloading the ${350                            type.prettyName()351                        } of $deviceName test run."352                    )353                }354            }355        }356    }357    "It should download all the reports even if any of them fails"{358        //GIVEN359        val expectedReports = (1..10)360            .map {361                tempfile("test_report_${it}_downloadable", ".zip")362            }363        val reportNotReadable = expectedReports.random()364        if (!reportNotReadable.setReadable(false)) fail("An error happens setting up the test")365        val destinyFolder = tempFolder("testReports")366        val run = Run367            .builder()368            .name("test run")369            .arn("arn:test:run")370            .build()371        val jobs = (1..10)372            .map { job ->373                Job374                    .builder()375                    .arn("arn:test:job:$job")376                    .name("test job $job")377                    .device {378                        it.name("Test device $job")379                            .arn("arn:test:device:$job")380                    }.build()381            }382        val artifacts = expectedReports383            .mapIndexed { index, associatedReport ->384                Artifact385                    .builder()386                    .arn("arn:test:artifact:$index")387                    .name(associatedReport.nameWithoutExtension)388                    .extension(associatedReport.extension)389                    .type(ArtifactType.CUSTOMER_ARTIFACT)390                    .url(associatedReport.toURI().toASCIIString())391                    .build()392            }393        val artifactsProvider = artifacts.iterator()394        val downloadArtifactsHandler = MockedDeviceFarmArtifactsHandler(395            getArtifactsImpl = {396                synchronized(this) {397                    Either.Right(listOf(artifactsProvider.next()))398                }399            }400        )401        val runHandler = MockedDeviceFarmRunsHandler(402            getAssociatedJobsImpl = { Either.Right(jobs) }403        )404        val reportDirectoryPath = Paths.get("test_reports_${run.name().lowercase().replace("\\s".toRegex(), "_")}")405        //WHEN406        DefaultDeviceFarmTractorController(407            logger,408            deviceFarmProjectsHandler,409            devicePoolsHandler,410            uploadArtifactsHandler,411            runHandler,412            downloadArtifactsHandler413        ).downloadAllEvidencesOfTestRun(run, destinyFolder, 0.milliseconds)414        //THEN415        destinyFolder shouldContainFile reportDirectoryPath.fileName.toString()416        destinyFolder shouldContainNFiles 1417        destinyFolder.resolve(reportDirectoryPath).shouldBeADirectory()418        destinyFolder.resolve(reportDirectoryPath) shouldContainNFiles jobs.size - 1419        destinyFolder420            .resolve(reportDirectoryPath)421            .listDirectoryEntries()422            .flatMap {423                it.listDirectoryEntries()424            }425            .map { it.fileName }426            .shouldContainExactlyInAnyOrder(427                expectedReports428                    .filter { it != reportNotReadable }429                    .map { it.toPath().fileName }430            )431    }432    "It should download all the recorded videos even if any of them fails"{433        //GIVEN434        val expectedRecordedVideos = (1..10)435            .map {436                tempfile("recorde_video_${it}_downloadable", ".mp4")437            }438        val recordedVideoNotReadable = expectedRecordedVideos.random()439        if (!recordedVideoNotReadable.setReadable(false)) fail("An error happens setting up the test")440        val destinyFolder = tempFolder("testResults")441        val run = Run442            .builder()443            .name("test run")444            .arn("arn:test:run")445            .build()446        val jobs = (1..10)447            .map { job ->448                Job449                    .builder()450                    .arn("arn:test:job:$job")451                    .name("test job $job")452                    .device {453                        it.name("Test device $job")454                            .arn("arn:test:device:$job")455                    }.build()456            }457        val artifacts = expectedRecordedVideos458            .mapIndexed { index, associatedVideo ->459                Artifact460                    .builder()461                    .arn("arn:test:artifact:$index")462                    .name(associatedVideo.nameWithoutExtension)463                    .extension(associatedVideo.extension)464                    .type(ArtifactType.VIDEO)465                    .url(associatedVideo.toURI().toASCIIString())466                    .build()467            }468        val artifactsProvider = artifacts.iterator()469        val downloadArtifactsHandler = MockedDeviceFarmArtifactsHandler(470            getArtifactsImpl = {471                synchronized(this) {472                    Either.Right(listOf(artifactsProvider.next()))473                }474            }475        )476        val runHandler = MockedDeviceFarmRunsHandler(477            getAssociatedJobsImpl = { Either.Right(jobs) }478        )479        val reportDirectoryPath = Paths.get("test_reports_${run.name().lowercase().replace("\\s".toRegex(), "_")}")480        //WHEN481        DefaultDeviceFarmTractorController(482            logger,483            deviceFarmProjectsHandler,484            devicePoolsHandler,485            uploadArtifactsHandler,486            runHandler,487            downloadArtifactsHandler488        ).downloadAllEvidencesOfTestRun(run, destinyFolder, 0.milliseconds)489        //THEN490        destinyFolder shouldContainFile reportDirectoryPath.fileName.toString()491        destinyFolder shouldContainNFiles 1492        destinyFolder.resolve(reportDirectoryPath).shouldBeADirectory()493        destinyFolder.resolve(reportDirectoryPath) shouldContainNFiles jobs.size - 1494        destinyFolder495            .resolve(reportDirectoryPath)496            .listDirectoryEntries()497            .flatMap {498                it.listDirectoryEntries()499            }500            .map { it.fileName }501            .shouldContainExactlyInAnyOrder(502                expectedRecordedVideos503                    .filter { it != recordedVideoNotReadable }504                    .map { it.toPath().fileName }505            )506    }507    "It should log an error message when creating the test report directory of an specific device fails"{508        //GIVEN509        val destinyFolder = tempFolder("testReports")510        val run = Run511            .builder()512            .name("test run")513            .arn("arn:test:run")514            .build()515        val job = Job516            .builder()517            .arn("arn:test:job")518            .name("test job")519            .device {520                it.name(deviceName)521                    .arn("arn:test:device")522            }.build()523        val downloadArtifactsHandler = MockedDeviceFarmArtifactsHandler(524            getArtifactsImpl = { fail("This should never been called") }525        )526        val runHandler = MockedDeviceFarmRunsHandler(527            getAssociatedJobsImpl = { Either.Right(listOf(job)) }528        )529        val reportDirectoryPath = destinyFolder530            .resolve("test_reports_${run.name().lowercase().replace("\\s".toRegex(), "_")}")531            .createDirectory()532        //WHEN533        val lastOutput = captureStandardOut {534            DefaultDeviceFarmTractorController(535                MockedDeviceFarmLogging(true),536                deviceFarmProjectsHandler,537                devicePoolsHandler,538                uploadArtifactsHandler,539                runHandler,540                downloadArtifactsHandler541            ).downloadAllEvidencesOfTestRun(run, destinyFolder, 0.milliseconds)542        }.lineSequence()543            .filter(String::isNotBlank)544            .map(String::trim)545            .last()546        //THEN547        reportDirectoryPath shouldContainNFiles 0548        lastOutput shouldStartWith "There was a problem creating the folder ${reportDirectoryPath.fileName}"549    }550    "It should log an error message when creating the test reports directory fails"{551        //GIVEN552        val destinyFolder = tempFolder("testReports")553        val run = Run554            .builder()555            .name("test run")556            .arn("arn:test:run")557            .build()558        val job = Job559            .builder()560            .arn("arn:test:job")561            .name("test job")562            .device {563                it.name(deviceName)564                    .arn("arn:test:device")565            }.build()566        val downloadArtifactsHandler = MockedDeviceFarmArtifactsHandler(567            getArtifactsImpl = { fail("This should never been called") }568        )569        val runHandler = MockedDeviceFarmRunsHandler(570            getAssociatedJobsImpl = { Either.Right(listOf(job)) }571        )572        val testReportsName = "test_reports_${run.name().lowercase().replace("\\s".toRegex(), "_")}"573        destinyFolder.toFile().setReadOnly()574        //WHEN575        val lastOutput = captureStandardOut {576            DefaultDeviceFarmTractorController(577                MockedDeviceFarmLogging(true),578                deviceFarmProjectsHandler,579                devicePoolsHandler,580                uploadArtifactsHandler,581                runHandler,582                downloadArtifactsHandler583            ).downloadAllEvidencesOfTestRun(run, destinyFolder, 0.milliseconds)584        }.lineSequence()585            .filter(String::isNotBlank)586            .map(String::trim)587            .last()588        //THEN589        destinyFolder shouldContainNFiles 0590        lastOutput shouldStartWith "There was a problem creating the folder $testReportsName"591    }592    "It should not try to download the reports when an error happens fetching the associated jobs of the test run"{593        //GIVEN594        val destinyFolder = tempFolder("testReports")595        val error = DeviceFarmTractorGeneralError(RuntimeException("test error"))596        val run = Run597            .builder()598            .name("test run")599            .arn("arn:test:run")600            .build()601        val downloadArtifactsHandler = MockedDeviceFarmArtifactsHandler(602            getArtifactsImpl = { fail("This should never been called") }603        )604        val runHandler = MockedDeviceFarmRunsHandler(605            getAssociatedJobsImpl = { Either.Left(error) }606        )607        //WHEN608        DefaultDeviceFarmTractorController(609            logger,610            deviceFarmProjectsHandler,611            devicePoolsHandler,612            uploadArtifactsHandler,613            runHandler,614            downloadArtifactsHandler615        ).downloadAllEvidencesOfTestRun(run, destinyFolder, 0.milliseconds)616        //THEN617        destinyFolder shouldContainNFiles 0618    }619    "It should download the recorded videos and test reports even if any of them fails"{620        //GIVEN621        val expectedReports = (1..10)622            .map {623                tempfile("test_report_${it}_downloadable", ".zip")624            }625        val expectedRecordedVideos = (1..10)626            .map {627                tempfile("test_video_${it}_downloadable", ".mp4")628            }629        val reportNotReadable = expectedReports.random()630        val videoNotReadable = expectedRecordedVideos.random()631        if (!reportNotReadable.setReadable(false)) fail("An error happens setting up the test")632        if (!videoNotReadable.setReadable(false)) fail("An error happens setting up the test")633        val destinyFolder = tempFolder("testReports")634        val run = Run635            .builder()636            .name("test run")637            .arn("arn:test:run")638            .build()639        val jobs = (1..10)640            .map { job ->641                Job642                    .builder()643                    .arn("arn:test:job:$job")644                    .name("test job $job")645                    .device {646                        it.name("Test device $job")647                            .arn("arn:test:device:$job")648                    }.build()649            }650        val customerArtifacts = expectedReports651            .mapIndexed { index, associatedReport ->652                Artifact653                    .builder()654                    .arn("arn:test:customer_artifact:$index")655                    .name(associatedReport.nameWithoutExtension)656                    .extension(associatedReport.extension)657                    .type(ArtifactType.CUSTOMER_ARTIFACT)658                    .url(associatedReport.toURI().toASCIIString())659                    .build()660            }661        val videoArtifacts = expectedRecordedVideos662            .mapIndexed { index, associatedVideo ->663                Artifact664                    .builder()665                    .arn("arn:test:video_artifact:$index")666                    .name(associatedVideo.nameWithoutExtension)667                    .extension(associatedVideo.extension)668                    .type(ArtifactType.VIDEO)669                    .url(associatedVideo.toURI().toASCIIString())670                    .build()671            }672        val customerArtifactsProvider = customerArtifacts.iterator()673        val videoArtifactsProvider = videoArtifacts.iterator()674        val downloadArtifactsHandler = MockedDeviceFarmArtifactsHandler(675            getArtifactsImpl = {676                synchronized(this) {677                    Either.Right(listOf(customerArtifactsProvider.next(), videoArtifactsProvider.next()))678                }679            }680        )681        val runHandler = MockedDeviceFarmRunsHandler(682            getAssociatedJobsImpl = { Either.Right(jobs) }683        )684        val reportDirectoryPath = Paths.get("test_reports_${run.name().lowercase().replace("\\s".toRegex(), "_")}")685        val expectedFiles = expectedReports686            .filter { it != reportNotReadable }687            .map { it.toPath().fileName } + expectedRecordedVideos688            .filter { it != videoNotReadable }689            .map { it.toPath().fileName }690        val expectedFilesSize =691            if (expectedReports.indexOf(reportNotReadable) == expectedRecordedVideos.indexOf(videoNotReadable)) jobs.size - 1 else jobs.size692        //WHEN693        DefaultDeviceFarmTractorController(694            logger,695            deviceFarmProjectsHandler,696            devicePoolsHandler,697            uploadArtifactsHandler,698            runHandler,699            downloadArtifactsHandler700        ).downloadAllEvidencesOfTestRun(run, destinyFolder, 0.milliseconds)701        //THEN702        destinyFolder shouldContainFile reportDirectoryPath.fileName.toString()703        destinyFolder shouldContainNFiles 1704        destinyFolder.resolve(reportDirectoryPath).shouldBeADirectory()705        destinyFolder.resolve(reportDirectoryPath) shouldContainNFiles expectedFilesSize706        destinyFolder707            .resolve(reportDirectoryPath)708            .listDirectoryEntries()709            .flatMap {710                it.listDirectoryEntries()711            }712            .map { it.fileName }713            .shouldContainExactlyInAnyOrder(expectedFiles)714    }715})...matchers.kt
Source:matchers.kt  
1package tutorial.kotest2import io.kotest.assertions.throwables.shouldThrow3import io.kotest.assertions.throwables.shouldThrowAny4import io.kotest.assertions.throwables.shouldThrowExactly5import io.kotest.core.spec.style.DescribeSpec6import io.kotest.core.test.AssertionMode7import io.kotest.matchers.booleans.shouldBeTrue8import io.kotest.matchers.collections.shouldBeIn9import io.kotest.matchers.collections.shouldBeOneOf10import io.kotest.matchers.collections.shouldBeSameSizeAs11import io.kotest.matchers.collections.shouldBeSingleton12import io.kotest.matchers.collections.shouldBeSmallerThan13import io.kotest.matchers.collections.shouldBeSorted14import io.kotest.matchers.collections.shouldBeUnique15import io.kotest.matchers.collections.shouldContain16import io.kotest.matchers.collections.shouldContainAll17import io.kotest.matchers.collections.shouldContainAnyOf18import io.kotest.matchers.collections.shouldContainDuplicates19import io.kotest.matchers.collections.shouldContainExactly20import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder21import io.kotest.matchers.collections.shouldContainInOrder22import io.kotest.matchers.collections.shouldContainNull23import io.kotest.matchers.collections.shouldEndWith24import io.kotest.matchers.collections.shouldHaveAtLeastSize25import io.kotest.matchers.collections.shouldHaveLowerBound26import io.kotest.matchers.collections.shouldHaveSingleElement27import io.kotest.matchers.collections.shouldHaveSize28import io.kotest.matchers.collections.shouldHaveUpperBound29import io.kotest.matchers.collections.shouldNotContainAnyOf30import io.kotest.matchers.collections.shouldNotHaveElementAt31import io.kotest.matchers.collections.shouldStartWith32import io.kotest.matchers.comparables.shouldBeEqualComparingTo33import io.kotest.matchers.comparables.shouldBeLessThanOrEqualTo34import io.kotest.matchers.date.shouldBeToday35import io.kotest.matchers.date.shouldHaveSameHoursAs36import io.kotest.matchers.doubles.Percentage37import io.kotest.matchers.doubles.beNaN38import io.kotest.matchers.doubles.plusOrMinus39import io.kotest.matchers.doubles.shouldBeNaN40import io.kotest.matchers.doubles.shouldNotBeNaN41import io.kotest.matchers.equality.shouldBeEqualToComparingFields42import io.kotest.matchers.equality.shouldBeEqualToComparingFieldsExcept43import io.kotest.matchers.equality.shouldBeEqualToIgnoringFields44import io.kotest.matchers.equality.shouldBeEqualToUsingFields45import io.kotest.matchers.file.shouldBeADirectory46import io.kotest.matchers.file.shouldBeAbsolute47import io.kotest.matchers.file.shouldExist48import io.kotest.matchers.file.shouldNotBeEmpty49import io.kotest.matchers.ints.beOdd50import io.kotest.matchers.ints.shouldBeBetween51import io.kotest.matchers.ints.shouldBeInRange52import io.kotest.matchers.ints.shouldBeLessThan53import io.kotest.matchers.ints.shouldBeLessThanOrEqual54import io.kotest.matchers.ints.shouldBeOdd55import io.kotest.matchers.ints.shouldBePositive56import io.kotest.matchers.ints.shouldBeZero57import io.kotest.matchers.iterator.shouldBeEmpty58import io.kotest.matchers.iterator.shouldHaveNext59import io.kotest.matchers.maps.shouldBeEmpty60import io.kotest.matchers.maps.shouldContain61import io.kotest.matchers.maps.shouldContainAll62import io.kotest.matchers.maps.shouldContainExactly63import io.kotest.matchers.maps.shouldContainKey64import io.kotest.matchers.nulls.shouldBeNull65import io.kotest.matchers.nulls.shouldNotBeNull66import io.kotest.matchers.shouldBe67import io.kotest.matchers.shouldNot68import io.kotest.matchers.shouldNotBe69import io.kotest.matchers.string.beEmpty70import io.kotest.matchers.string.shouldBeBlank71import io.kotest.matchers.string.shouldBeEmpty72import io.kotest.matchers.string.shouldBeEqualIgnoringCase73import io.kotest.matchers.string.shouldBeInteger74import io.kotest.matchers.string.shouldBeLowerCase75import io.kotest.matchers.string.shouldBeUpperCase76import io.kotest.matchers.string.shouldContain77import io.kotest.matchers.string.shouldContainADigit78import io.kotest.matchers.string.shouldContainIgnoringCase79import io.kotest.matchers.string.shouldContainOnlyDigits80import io.kotest.matchers.string.shouldContainOnlyOnce81import io.kotest.matchers.string.shouldEndWith82import io.kotest.matchers.string.shouldHaveLength83import io.kotest.matchers.string.shouldHaveLineCount84import io.kotest.matchers.string.shouldHaveMaxLength85import io.kotest.matchers.string.shouldHaveMinLength86import io.kotest.matchers.string.shouldHaveSameLengthAs87import io.kotest.matchers.string.shouldMatch88import io.kotest.matchers.string.shouldNotBeEmpty89import io.kotest.matchers.string.shouldStartWith90import io.kotest.matchers.throwable.shouldHaveCause91import io.kotest.matchers.throwable.shouldHaveCauseInstanceOf92import io.kotest.matchers.throwable.shouldHaveCauseOfType93import io.kotest.matchers.throwable.shouldHaveMessage94import io.kotest.matchers.types.shouldBeInstanceOf95import io.kotest.matchers.types.shouldBeSameInstanceAs96import io.kotest.matchers.types.shouldBeTypeOf97import io.kotest.matchers.uri.shouldHaveHost98import io.kotest.matchers.uri.shouldHavePort99import io.kotest.matchers.uri.shouldHaveScheme100import java.io.File101import java.net.URI102import java.time.LocalDate103import java.time.LocalTime104// https://kotest.io/docs/assertions/core-matchers.html105class MatchersTest : DescribeSpec({106    describe("general") {107        it("basics") {108            (1 == 1).shouldBeTrue()109            (2 + 2) shouldBe 4110            val foo: Any = "foobar"111            foo.shouldBeTypeOf<String>() shouldContain "fo"112            "".shouldBeEmpty()113            "x".shouldNot(beEmpty()) // manually negate114            "x".shouldNotBeEmpty() // reusable115            URI("https://tba") shouldHaveHost "tba"116            URI("https://tba:81") shouldHavePort 81117            URI("https://tba") shouldHaveScheme "https"118            File("/").apply {119                shouldExist()120                shouldBeADirectory()121                shouldBeAbsolute()122                shouldNotBeEmpty()123            }124            // executable, hidden, readable, smaller, writeable, containFile, extension, path, ...125            LocalDate.now().shouldBeToday()126            // before/after, within, same, between, have year/month/day/hour/...127            LocalTime.now().shouldHaveSameHoursAs(LocalTime.now())128            // before/after/between, sameMinute/Seconds/Nanos129        }130        it("numbers") {131            1 shouldBeLessThan 2132            1 shouldBeLessThanOrEqual 1 // Int-based; returns this133            1 shouldBeLessThanOrEqualTo 1 // Comparble-based; void134            1 shouldBeEqualComparingTo 1 // Comparable-based135            1.shouldBeBetween(0, 2)136            1 shouldBeInRange 0..2137            0.shouldBeZero()138            1.shouldBePositive()139            1.shouldBeOdd()140            (1.2).shouldBe(1.20001.plusOrMinus(Percentage(20.0)))141            (1.2).shouldNotBeNaN()142        }143        it("strings") {144            // generic: "abc" shouldBe "abc"145            "aBc" shouldBeEqualIgnoringCase "abc"146            "".shouldBeEmpty()147            " ".shouldBeBlank() // empty or whitespace148            "abc" shouldContain ("b")149            "aBc" shouldContainIgnoringCase "bc"150            "x-a-x" shouldContain """\-[a-z]\-""".toRegex()151            "-a-" shouldMatch """\-[a-z]\-""".toRegex()152            "abc" shouldStartWith ("a")153            "abc" shouldEndWith ("c")154            "ab aa" shouldContainOnlyOnce "aa"155            "abc".shouldBeLowerCase()156            "ABC".shouldBeUpperCase()157            "abc" shouldHaveLength 3158            "a\nb" shouldHaveLineCount 2159            "ab" shouldHaveMinLength 1 shouldHaveMaxLength 3160            "abc" shouldHaveSameLengthAs "foo"161            "1".shouldBeInteger()162            "12".shouldContainOnlyDigits()163            "abc1".shouldContainADigit() // at least one164        }165        it("types") {166            @Connotation167            open class SuperType()168            class SubType : SuperType()169            val sameRef = SuperType()170            sameRef.shouldBeSameInstanceAs(sameRef)171            val superType: SuperType = SubType()172            superType.shouldBeTypeOf<SubType>() // exact runtime match (SuperType won't work!)173            superType.shouldBeInstanceOf<SuperType>() // T or below174//            SubType().shouldHaveAnnotation(Connotation::class)175            val nullable: String? = null176            nullable.shouldBeNull()177        }178        it("collections") {179            emptyList<Int>().iterator().shouldBeEmpty()180            listOf(1).iterator().shouldHaveNext()181            listOf(1, 2) shouldContain 1 // at least182            listOf(1, 2) shouldContainExactly listOf(1, 2) // in-order; not more183            listOf(1, 2) shouldContainExactlyInAnyOrder listOf(2, 1) // out-order; not more184            listOf(0, 3, 0, 4, 0).shouldContainInOrder(3, 4) // possible items in between185            listOf(1) shouldNotContainAnyOf listOf(2, 3) // black list186            listOf(1, 2, 3) shouldContainAll listOf(3, 2) // out-order; more187            listOf(1, 2, 3).shouldBeUnique() // no duplicates188            listOf(1, 2, 2).shouldContainDuplicates() // at least one duplicate189            listOf(1, 2).shouldNotHaveElementAt(1, 3)190            listOf(1, 2) shouldStartWith 1191            listOf(1, 2) shouldEndWith 2192            listOf(1, 2) shouldContainAnyOf listOf(2, 3)193            val x = SomeType(1)194            x shouldBeOneOf listOf(x) // by reference/instance195            x shouldBeIn listOf(SomeType(1)) // by equality/structural196            listOf(1, 2, null).shouldContainNull()197            listOf(1) shouldHaveSize 1198            listOf(1).shouldBeSingleton() // size == 1199            listOf(1).shouldBeSingleton {200                it.shouldBeOdd()201            }202            listOf(1).shouldHaveSingleElement {203                beOdd().test(it).passed() // have to return a boolean here :-/204            }205            listOf(2, 3) shouldHaveLowerBound 1 shouldHaveUpperBound 4206            listOf(1) shouldBeSmallerThan listOf(1, 2)207            listOf(1) shouldBeSameSizeAs listOf(2)208            listOf(1, 2) shouldHaveAtLeastSize 1209            listOf(1, 2).shouldBeSorted()210            mapOf(1 to "a").shouldContain(1, "a") // at least this211            mapOf(1 to "a") shouldContainAll mapOf(1 to "a") // at least those212            mapOf(1 to "a") shouldContainExactly mapOf(1 to "a") // not more213            mapOf(1 to "a") shouldContainKey 1214            emptyMap<Any, Any>().shouldBeEmpty()215        }216        it("exceptions") {217            class SubException() : Exception()218            Exception("a") shouldHaveMessage "a" // same (not contains!)219            Exception("abc").message shouldContain "b"220            Exception("", Exception()).shouldHaveCause()221            Exception("symptom", Exception("cause")).shouldHaveCause {222                it.message shouldBe "cause"223            }224            Exception("", SubException()).shouldHaveCauseInstanceOf<Exception>() // T or subclass225            Exception("", SubException()).shouldHaveCauseOfType<SubException>() // exactly T226            shouldThrow<Exception> { // type or subtype227                throw SubException()228            }229            shouldThrowExactly<Exception> { // exactly that type (no subtype!)230                throw Exception()231            }232            shouldThrowAny { // don't care which233                throw Exception()234            }235        }236    }237    describe("advanced") {238        it("selective matcheres") {239            data class Foo(val p1: Int, val p2: Int)240            val foo1 = Foo(1, 1)241            val foo2 = Foo(1, 2)242            foo1.shouldBeEqualToUsingFields(foo2, Foo::p1)243            foo1.shouldBeEqualToIgnoringFields(foo2, Foo::p2)244            class Bar(val p1: Int, val p2: Int) // not a data class! no equals.245            val bar1a = Bar(1, 1)246            val bar1b = Bar(1, 1)247            bar1a shouldNotBe bar1b248            bar1a shouldBeEqualToComparingFields bar1b // "fake equals" (ignoring private properties)249            bar1a.shouldBeEqualToComparingFields(bar1b, false) // explicitly also check private props250            val bar2 = Bar(1, 2)251            bar1a.shouldBeEqualToComparingFieldsExcept(bar2, Bar::p2)252        }253    }254    // channels255    // concurrent, futures256    // result, optional257    // threads258    // reflection259    // statistic, regex260})261private data class SomeType(val value: Int = 1)262private annotation class Connotation...BuildDocsTest.kt
Source:BuildDocsTest.kt  
1package com.javiersc.gradle.plugins.docs2import com.javiersc.gradle.plugins.core.test.arguments3import com.javiersc.gradle.plugins.core.test.getResource4import com.javiersc.gradle.plugins.core.test.taskFromArguments5import com.javiersc.gradle.plugins.core.test.testSandbox6import io.kotest.matchers.file.shouldBeADirectory7import io.kotest.matchers.file.shouldBeAFile8import io.kotest.matchers.file.shouldHaveSameStructureAndContentAs9import io.kotest.matchers.nulls.shouldNotBeNull10import io.kotest.matchers.shouldBe11import io.kotest.matchers.string.shouldContain12import java.io.File13import kotlin.test.Ignore14import kotlin.test.Test15import org.gradle.testkit.runner.BuildResult16import org.gradle.testkit.runner.TaskOutcome17class BuildDocsTest {18    @Test19    fun `build docs`() {20        val docsDir: File = getResource("docs")21        val sandboxDirs: List<File> =22            checkNotNull(docsDir.listFiles()).toList().filterNot {23                it.isFile || (it.isDirectory && it.name.endsWith("-actual"))24            }25        for (dir in sandboxDirs) {26            val sandboxPath = dir.toRelativeString(docsDir.parentFile).replace("\\", "/")27            val actualPath = "$sandboxPath-actual/.docs"28            testSandbox(29                sandboxPath = sandboxPath,30                test = { _: BuildResult, testProjectDir: File ->31                    val expect = File("$testProjectDir/build/.docs/")32                    val actual: File = getResource(actualPath)33                    expect shouldHaveSameStructureAndContentAs actual34                    File("$testProjectDir/build/.docs/").shouldBeADirectory()35                    File("$testProjectDir/build/docs/").shouldBeADirectory()36                    val siteDir = File("$testProjectDir/build/docs/_site/")37                    File("$siteDir/index.html").shouldBeAFile()38                    File("$siteDir/api/").shouldBeADirectory()39                    if (sandboxPath.contains("snapshot")) {40                        File("$siteDir/api/snapshot/").shouldBeADirectory()41                    } else {42                        File("$siteDir/api/versions/").shouldBeADirectory()43                    }44                }45            )46        }47    }48    @Test49    fun `build cache docs`() {50        // to simulate IDEA sync the task is run three times51        val (runner, testProjectDir) =52            testSandbox(53                sandboxPath = "docs-gradle-features/build-cache-1",54                isBuildCacheTest = true,55                test = { result: BuildResult, testProjectDir: File ->56                    result57                        .task(":${testProjectDir.taskFromArguments}")58                        .shouldNotBeNull()59                        .outcome.shouldBe(TaskOutcome.SUCCESS)60                }61            )62        File("$testProjectDir/build").deleteRecursively()63        runner.withArguments(testProjectDir.arguments).build()64        File("$testProjectDir/build").deleteRecursively()65        val result = runner.withArguments(testProjectDir.arguments).build()66        result67            .task(":${testProjectDir.taskFromArguments}")68            .shouldNotBeNull()69            .outcome.shouldBe(TaskOutcome.FROM_CACHE)70    }71    @Ignore("MkDocs Gradle plugin needs to be compatible with Configuration cache (grgit issue)")72    @Test73    fun `configuration cache docs`() {74        val (runner, testProjectDir) =75            testSandbox(76                sandboxPath = "docs-gradle-features/configuration-cache-1",77                test = { result: BuildResult, testProjectDir: File ->78                    result79                        .task(":${testProjectDir.taskFromArguments}")80                        .shouldNotBeNull()81                        .outcome.shouldBe(TaskOutcome.SUCCESS)82                }83            )84        val result = runner.withArguments(testProjectDir.arguments + "--info").build()85        println("----------------")86        println(result.output)87        println("----------------")88        result.output.shouldContain("Reusing configuration cache")89        result90            .task(":${testProjectDir.taskFromArguments}")91            .shouldNotBeNull()92            .outcome.shouldBe(TaskOutcome.UP_TO_DATE)93    }94}...WebappTest.kt
Source:WebappTest.kt  
1package family.haschka.wolkenschloss.conventions2import io.kotest.assertions.assertSoftly3import io.kotest.core.spec.style.DescribeSpec4import io.kotest.matchers.collections.shouldContainAll5import io.kotest.matchers.file.shouldBeADirectory6import io.kotest.matchers.file.shouldContainFile7import io.kotest.matchers.file.shouldExist8import io.kotest.matchers.shouldBe9import org.gradle.testkit.runner.TaskOutcome10import family.haschka.wolkenschloss.testing.Template11import family.haschka.wolkenschloss.testing.build12class WebappTest : DescribeSpec({13    describe("project with vue application") {14        val fixture = autoClose(Template("webapp"))15        describe("build task") {16            it("should create jar file") {17                fixture.withClone {18                    val result = build("build")19                    result.task(":build")!!.outcome shouldBe TaskOutcome.SUCCESS20                    result.task(":vue")!!.outcome shouldBe TaskOutcome.SUCCESS21                    workingDirectory.resolve("build/libs/fixture-webapp.jar").shouldExist()22                }23            }24        }25        describe("check task") {26            it("should run unit and e2e tasks") {27                fixture.withClone {28                    val result = build("check")29                    result.tasks(TaskOutcome.SUCCESS)30                        .map { task -> task.path }31                        .shouldContainAll(":unit", ":e2e", ":check")32                }33            }34        }35        describe("vue task") {36            it("should build vue app") {37                fixture.withClone {38                    val result = build("vue")39                    result.task(":vue")!!.outcome shouldBe TaskOutcome.SUCCESS40                    assertSoftly(workingDirectory.resolve("build/classes/java/main/META-INF/resources")) {41                        shouldBeADirectory()42                        shouldContainFile("index.html")43                        resolve("js").shouldBeADirectory()44                    }45                }46            }47        }48        describe("unit task") {49            it("should run unit tests") {50                fixture.withClone {51                    val result = build("unit")52                    result.task(":unit")!!.outcome shouldBe TaskOutcome.SUCCESS53                    workingDirectory.resolve("build/reports/tests/unit").shouldContainFile("junit.xml")54                }55            }56        }57        describe("e2e task") {58            it("should run e2e tests") {59                fixture.withClone {60                    val result = build("e2e")61                    result.task(":e2e")!!.outcome shouldBe TaskOutcome.SUCCESS62                    workingDirectory.resolve("build/reports/tests/e2e").shouldBeADirectory()63                }64            }65        }66    }67})...IOSpec.kt
Source:IOSpec.kt  
1package com.github.rougsig.core2import io.kotest.core.datatest.forAll3import io.kotest.core.spec.style.FunSpec4import io.kotest.matchers.file.shouldBeADirectory5import io.kotest.matchers.file.shouldBeAFile6import io.kotest.matchers.file.shouldExist7import io.kotest.matchers.shouldBe8import kotlinx.coroutines.runBlocking9import java.io.ByteArrayInputStream10import java.io.ByteArrayOutputStream11import java.io.File12import java.io.PrintStream13import java.nio.file.Paths14abstract class IOSpec(15  private val resourcesPath: String,16  private val testFun: IOEnvironment.() -> Unit17) : FunSpec({18  val projectRoot = File(".").absoluteFile.parent19  val resourcesDir = Paths.get(projectRoot, "src/test/resources", resourcesPath).toFile()20  context("File IO tests") {21    val inputDir = File("${resourcesDir.absoluteFile}/input")22    inputDir.shouldExist()23    inputDir.shouldBeADirectory()24    val outputDir = File("${resourcesDir.absoluteFile}/output")25    outputDir.shouldExist()26    val testNames = inputDir.listFiles()27      .map { it.nameWithoutExtension.removePrefix("input") }28    forAll(testNames) { testName: String ->29      val input = File("${inputDir.absoluteFile}/input${testName}.txt")30      input.shouldExist()31      input.shouldBeAFile()32      val output = File("${outputDir.absoluteFile}/output${testName}.txt")33      output.shouldExist()34      output.shouldBeAFile()35      val baos = ByteArrayOutputStream()36      runBlocking {37        // Set the same as hackerrank timeout limit38        // https://www.hackerrank.com/environment/languages39        withTimeoutOrInterrupt(4000L) {40          IOEnvironment(ByteArrayInputStream(input.readBytes()), PrintStream(baos)).testFun()41        }42      }43      val actual = baos.toString().trim().trimIndent()44      val expected = output.readText().trim().trimIndent()45      actual.shouldBe(expected)46    }47  }48})...ScenarioTest.kt
Source:ScenarioTest.kt  
1package uk.nhs.riskscore2import io.kotest.core.spec.style.StringSpec3import io.kotest.matchers.doubles.shouldBeLessThan4import io.kotest.matchers.paths.*5import uk.nhs.riskscore.RiskScoreCalculatorConfiguration.Companion.exampleConfiguration6import uk.nhs.support.InstanceName7import uk.nhs.support.RiskScoreResultsCSVDecoder8import uk.nhs.support.ScanInstanceCSVDecoder9import java.nio.file.Paths10import kotlin.math.abs11internal class ScenarioTest: StringSpec({12    "computed riskscores are within 5% of the python computed riskscores" {13        val rootPath = Paths.get("src","test","resources", "TestData").toAbsolutePath()14        val expectedRiskScoresPath = rootPath.resolve("pythonRiskScores.csv")15        expectedRiskScoresPath.shouldBeAFile()16        val scanInstanceDirectoryPath = Paths.get(rootPath.toString(), "ScanInstances")17        scanInstanceDirectoryPath.shouldBeADirectory()18        val calculator = RiskScoreCalculator(exampleConfiguration)19        val expectedScores = RiskScoreResultsCSVDecoder.decode(expectedRiskScoresPath.toFile().path)20        scanInstanceDirectoryPath.toFile().listFiles()!!.forEach { scanInstanceFile ->21            val instances = ScanInstanceCSVDecoder.decode(scanInstanceFile.path)22            val actualScore = calculator.calculate(instances)23            val expectedScore = expectedScores[InstanceName(scanInstanceFile.name)]!!.score24            abs(expectedScore - actualScore) shouldBeLessThan (actualScore * 0.05)25        }26    }27})...CodeFormatterTest.kt
Source:CodeFormatterTest.kt  
1package com.javiersc.gradle.plugins.code.formatter2import com.javiersc.gradle.plugins.core.test.getResource3import com.javiersc.gradle.plugins.core.test.testSandbox4import io.kotest.matchers.collections.shouldBeSameSizeAs5import io.kotest.matchers.file.shouldBeADirectory6import io.kotest.matchers.file.shouldHaveSameContentAs7import java.io.File8import kotlin.test.Test9import org.gradle.testkit.runner.BuildResult10class CodeFormatterTest {11    @Test12    fun `format 1`() {13        testSandbox(sandboxPath = "sandbox-format-1", test = ::testFormatter)14    }15}16@Suppress("UNUSED_PARAMETER")17fun testFormatter(result: BuildResult, testProjectDir: File) {18    val expect = File("$testProjectDir/library/")19    val actual: File = getResource("sandbox-format-1-actual/library")20    val expectFiles: List<File> =21        expect.walkTopDown().toList().filter { it.path.contains("spotless").not() }22    val actualFiles: List<File> =23        actual.walkTopDown().toList().filter { it.path.contains("spotless").not() }24    expectFiles shouldBeSameSizeAs actualFiles25    expectFiles.zip(actualFiles).forEach { (expect, actual) ->26        when {27            expect.isDirectory -> actual.shouldBeADirectory()28            expect.isFile -> expect.shouldHaveSameContentAs(actual)29            else -> error("Unexpected error analyzing file trees")30        }31    }32}...TranslationProcessorTest.kt
Source:TranslationProcessorTest.kt  
1import com.tschuchort.compiletesting.*2import com.tschuchort.compiletesting.KotlinCompilation.ExitCode3import de.f0x.lokales.internal.processor.TranslationProcessor4import io.kotest.core.spec.style.StringSpec5import io.kotest.matchers.file.shouldBeADirectory6import io.kotest.matchers.file.shouldNotBeEmptyDirectory7import io.kotest.matchers.shouldBe8class TranslationProcessorTest : StringSpec({9    "processor should generate file" {10        val dummySource = SourceFile.kotlin(11            "TestFile.kt", """12        package de.f0x.lokales.test13        """14        )15        val compilation = KotlinCompilation().apply {16            sources = listOf(dummySource)17            symbolProcessors = listOf(TranslationProcessor())18            kspArgs["pkg"] = "de.f0x.lokales.test"19            kspArgs["upTo"] = "10"20        }21        val result = compilation.compile()22        result.exitCode shouldBe ExitCode.OK23        compilation.kspSourcesDir.shouldBeADirectory()24        compilation.kspSourcesDir.shouldNotBeEmptyDirectory()25    }26})...File.shouldBeADirectory
Using AI Code Generation
1File("src/test/resources").shouldBeADirectory()2File("src/test/resources/test.txt").shouldBeAFile()3File("src/test/resources/test.txt").shouldBeAHiddenFile()4File("src/test/resources/test.txt").shouldBeAnEmptyFile()5File("src/test/resources").shouldBeAnEmptyDirectory()6File("src/test/resources/test.txt").shouldBeAReadableFile()7File("src/test/resources").shouldBeAReadableDirectory()8File("src/test/resources/test.txt").shouldBeAWritableFile()9File("src/test/resources").shouldBeAWritableDirectory()10File("src/test/resources/test.txt").shouldBeAnExecutableFile()11File("src/test/resources").shouldBeAnExecutableDirectory()12File("src/test/resources/test.txt").shouldBeAnExistingFile()13File("src/test/resources").shouldBeAnExistingDirectory()14File("src/test/resources/test.txt").shouldBeAnExistingPath()15File("src/test/resources/test.txt").shouldHaveExtensionFile.shouldBeADirectory
Using AI Code Generation
1File(“/Users/username/Downloads”).shouldBeADirectory()2File(“/Users/username/Downloads/file.txt”).shouldBeARegularFile()3File(“/Users/username/Downloads/file.txt”).shouldBeAHiddenFile()4File(“/Users/username/Downloads/file.txt”).shouldBeAReadableFile()5File(“/Users/username/Downloads/file.txt”).shouldBeAExecutableFile()6File(“/Users/username/Downloads/file.txt”).shouldBeAWriteableFile()7File(“/Users/username/Downloads/file.txt”).shouldBeAHiddenFile()8File(“/Users/username/Downloads/file.txt”).shouldBeAWriteableFile()9File(“/Users/username/Downloads/file.txt”).shouldBeAReadableFile()10File(“/Users/username/Downloads/file.txt”).shouldBeAExecutableFile()11File(“/Users/username/Downloads/file.txt”).shouldBeAWriteableFile()12File(“/Users/username/Downloads/file.txt”).shouldBeAHiddenFile()13File(“/Users/username/Downloads/file.txt”).shouldBeAFile.shouldBeADirectory
Using AI Code Generation
1File( "src" ).shouldBeADirectory()2File( "src/main/kotlin" ).shouldBeAFile()3File( "src/main/kotlin" ).shouldBeAbsolute()4File( "src/main/kotlin" ).shouldBeRelative()5File( "src/main/kotlin" ).shouldBeHidden()6File( "src/main/kotlin" ).shouldBeReadable()7File( "src/main/kotlin" ).shouldBeWritable()8File( "src/main/kotlin" ).shouldBeExecutable()9File( "src/main/kotlin" ).shouldBeEmptyDirectory()10File( "src/main/kotlin" ).shouldBeEmpty()11File( "src/main/kotlin" ).shouldBeSymbolicLink()Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
