How to use Exhaustive.zip method of io.kotest.property.exhaustive.zip class

Best Kotest code snippet using io.kotest.property.exhaustive.zip.Exhaustive.zip

WhenDownloadingAwsDeviceFarmArtifacts.kt

Source:WhenDownloadingAwsDeviceFarmArtifacts.kt Github

copy

Full Screen

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})...

Full Screen

Full Screen

proptest.kt

Source:proptest.kt Github

copy

Full Screen

1package io.kotest.property.internal2import io.kotest.property.Arb3import io.kotest.property.Constraints4import io.kotest.property.Exhaustive5import io.kotest.property.Gen6import io.kotest.property.PropTestConfig7import io.kotest.property.PropertyContext8import io.kotest.property.PropertyTesting9import io.kotest.property.classifications.outputClassifications10import io.kotest.property.seed.createRandom11suspend fun <A> proptest(12 genA: Gen<A>,13 config: PropTestConfig,14 property: suspend PropertyContext.(A) -> Unit15): PropertyContext {16 config.checkFailOnSeed()17 val constraints = config.constraints18 ?: config.iterations?.let { Constraints.iterations(it) }19 ?: Constraints.iterations(PropertyTesting.defaultIterationCount)20 val context = PropertyContext()21 val random = createRandom(config)22 when (genA) {23 is Arb -> {24 genA.generate(random, config.edgeConfig)25 .takeWhile { constraints.evaluate() }26 .forEach { a ->27 val shrinkfn = shrinkfn(a, property, config.shrinkingMode)28 config.listeners.forEach { it.beforeTest() }29 test(30 context,31 config,32 shrinkfn,33 listOf(a.value),34 listOf(genA.classifier),35 random.seed36 ) {37 context.property(a.value)38 }39 config.listeners.forEach { it.afterTest() }40 }41 }42 is Exhaustive -> {43 genA.values.forEach { a ->44 config.listeners.forEach { it.beforeTest() }45 test(46 context,47 config,48 { emptyList() },49 listOf(a),50 listOf(genA.classifier),51 random.seed52 ) {53 context.property(a)54 }55 config.listeners.forEach { it.afterTest() }56 }57 }58 }59 context.outputClassifications(1, config, random.seed)60 context.checkMaxSuccess(config, random.seed)61 return context62}63suspend fun <A, B> proptest(64 genA: Gen<A>,65 genB: Gen<B>,66 config: PropTestConfig,67 property: suspend PropertyContext.(A, B) -> Unit68): PropertyContext {69 config.checkFailOnSeed()70 val constraints = config.constraints71 ?: config.iterations?.let { Constraints.iterations(it) }72 ?: Constraints.iterations(PropertyTesting.defaultIterationCount)73 val context = PropertyContext()74 val random = createRandom(config)75 if (genA is Exhaustive && genB is Exhaustive) {76 genA.values.forEach { a ->77 genB.values.forEach { b ->78 config.listeners.forEach { it.beforeTest() }79 test(80 context,81 config,82 { emptyList() },83 listOf(a, b),84 listOf(genA.classifier, genB.classifier),85 random.seed86 ) {87 context.property(a, b)88 }89 config.listeners.forEach { it.afterTest() }90 }91 }92 } else {93 genA.generate(random, config.edgeConfig)94 .zip(genB.generate(random, config.edgeConfig))95 .takeWhile { constraints.evaluate() }96 .forEach { (a, b) ->97 val shrinkfn = shrinkfn(a, b, property, config.shrinkingMode)98 config.listeners.forEach { it.beforeTest() }99 test(100 context,101 config,102 shrinkfn,103 listOf(a.value, b.value),104 listOf(genA.classifier, genB.classifier),105 random.seed106 ) {107 context.property(a.value, b.value)108 }109 config.listeners.forEach { it.afterTest() }110 }111 }112 context.outputClassifications(2, config, random.seed)113 context.checkMaxSuccess(config, random.seed)114 return context115}116suspend fun <A, B, C> proptest(117 genA: Gen<A>,118 genB: Gen<B>,119 genC: Gen<C>,120 config: PropTestConfig,121 property: suspend PropertyContext.(A, B, C) -> Unit122): PropertyContext {123 config.checkFailOnSeed()124 val constraints = config.constraints125 ?: config.iterations?.let { Constraints.iterations(it) }126 ?: Constraints.iterations(PropertyTesting.defaultIterationCount)127 val context = PropertyContext()128 val random = createRandom(config)129 if (genA is Exhaustive && genB is Exhaustive && genC is Exhaustive) {130 genA.values.forEach { a ->131 genB.values.forEach { b ->132 genC.values.forEach { c ->133 config.listeners.forEach { it.beforeTest() }134 test(135 context,136 config,137 { emptyList() },138 listOf(a, b, c),139 listOf(genA.classifier, genB.classifier, genC.classifier),140 random.seed141 ) {142 context.property(a, b, c)143 }144 config.listeners.forEach { it.afterTest() }145 }146 }147 }148 } else {149 genA.generate(random, config.edgeConfig)150 .zip(genB.generate(random, config.edgeConfig))151 .zip(genC.generate(random, config.edgeConfig))152 .takeWhile { constraints.evaluate() }153 .forEach { (ab, c) ->154 val (a, b) = ab155 val shrinkfn = shrinkfn(a, b, c, property, config.shrinkingMode)156 config.listeners.forEach { it.beforeTest() }157 test(158 context,159 config,160 shrinkfn,161 listOf(a.value, b.value, c.value),162 listOf(genA.classifier, genB.classifier, genC.classifier),163 random.seed164 ) {165 context.property(a.value, b.value, c.value)166 }167 config.listeners.forEach { it.afterTest() }168 }169 }170 context.outputClassifications(3, config, random.seed)171 context.checkMaxSuccess(config, random.seed)172 return context173}174suspend fun <A, B, C, D> proptest(175 genA: Gen<A>,176 genB: Gen<B>,177 genC: Gen<C>,178 genD: Gen<D>,179 config: PropTestConfig,180 property: suspend PropertyContext.(A, B, C, D) -> Unit181): PropertyContext {182 config.checkFailOnSeed()183 val constraints = config.constraints184 ?: config.iterations?.let { Constraints.iterations(it) }185 ?: Constraints.iterations(PropertyTesting.defaultIterationCount)186 val context = PropertyContext()187 val random = createRandom(config)188 if (genA is Exhaustive && genB is Exhaustive && genC is Exhaustive && genD is Exhaustive) {189 genA.values.forEach { a ->190 genB.values.forEach { b ->191 genC.values.forEach { c ->192 genD.values.forEach { d ->193 config.listeners.forEach { it.beforeTest() }194 test(195 context, config, { emptyList() }, listOf(a, b, c, d),196 listOf(genA.classifier, genB.classifier, genC.classifier, genD.classifier), random.seed197 ) {198 context.property(a, b, c, d)199 }200 config.listeners.forEach { it.afterTest() }201 }202 }203 }204 }205 } else {206 genA.generate(random, config.edgeConfig)207 .zip(genB.generate(random, config.edgeConfig))208 .zip(genC.generate(random, config.edgeConfig))209 .zip(genD.generate(random, config.edgeConfig))210 .takeWhile { constraints.evaluate() }211 .forEach { (abc, d) ->212 val (ab, c) = abc213 val (a, b) = ab214 val shrinkfn = shrinkfn(a, b, c, d, property, config.shrinkingMode)215 config.listeners.forEach { it.beforeTest() }216 test(217 context, config, shrinkfn,218 listOf(a.value, b.value, c.value, d.value),219 listOf(genA.classifier, genB.classifier, genC.classifier, genD.classifier),220 random.seed221 ) {222 context.property(a.value, b.value, c.value, d.value)223 }224 config.listeners.forEach { it.afterTest() }225 }226 }227 context.outputClassifications(4, config, random.seed)228 context.checkMaxSuccess(config, random.seed)229 return context230}231suspend fun <A, B, C, D, E> proptest(232 genA: Gen<A>,233 genB: Gen<B>,234 genC: Gen<C>,235 genD: Gen<D>,236 genE: Gen<E>,237 config: PropTestConfig,238 property: suspend PropertyContext.(A, B, C, D, E) -> Unit239): PropertyContext {240 config.checkFailOnSeed()241 val constraints = config.constraints242 ?: config.iterations?.let { Constraints.iterations(it) }243 ?: Constraints.iterations(PropertyTesting.defaultIterationCount)244 val context = PropertyContext()245 val random = createRandom(config)246 if (genA is Exhaustive && genB is Exhaustive && genC is Exhaustive && genD is Exhaustive && genE is Exhaustive) {247 genA.values.forEach { a ->248 genB.values.forEach { b ->249 genC.values.forEach { c ->250 genD.values.forEach { d ->251 genE.values.forEach { e ->252 config.listeners.forEach { it.beforeTest() }253 test(254 context,255 config,256 { emptyList() },257 listOf(a, b, c, d, e),258 listOf(259 genA.classifier,260 genB.classifier,261 genC.classifier,262 genD.classifier,263 genE.classifier,264 ),265 random.seed266 ) {267 context.property(a, b, c, d, e)268 }269 config.listeners.forEach { it.afterTest() }270 }271 }272 }273 }274 }275 } else {276 genA.generate(random, config.edgeConfig)277 .zip(genB.generate(random, config.edgeConfig))278 .zip(genC.generate(random, config.edgeConfig))279 .zip(genD.generate(random, config.edgeConfig))280 .zip(genE.generate(random, config.edgeConfig))281 .takeWhile { constraints.evaluate() }282 .forEach { (abcd, e) ->283 val (abc, d) = abcd284 val (ab, c) = abc285 val (a, b) = ab286 val shrinkfn = shrinkfn(a, b, c, d, e, property, config.shrinkingMode)287 config.listeners.forEach { it.beforeTest() }288 test(289 context,290 config,291 shrinkfn,292 listOf(a.value, b.value, c.value, d.value, e.value),293 listOf(294 genA.classifier,295 genB.classifier,296 genC.classifier,297 genD.classifier,298 genE.classifier,299 ),300 random.seed301 ) {302 context.property(a.value, b.value, c.value, d.value, e.value)303 }304 config.listeners.forEach { it.afterTest() }305 }306 }307 context.outputClassifications(5, config, random.seed)308 context.checkMaxSuccess(config, random.seed)309 return context310}311suspend fun <A, B, C, D, E, F> proptest(312 genA: Gen<A>,313 genB: Gen<B>,314 genC: Gen<C>,315 genD: Gen<D>,316 genE: Gen<E>,317 genF: Gen<F>,318 config: PropTestConfig,319 property: suspend PropertyContext.(A, B, C, D, E, F) -> Unit320): PropertyContext {321 config.checkFailOnSeed()322 val constraints = config.constraints323 ?: config.iterations?.let { Constraints.iterations(it) }324 ?: Constraints.iterations(PropertyTesting.defaultIterationCount)325 val context = PropertyContext()326 val random = createRandom(config)327 genA.generate(random, config.edgeConfig)328 .zip(genB.generate(random, config.edgeConfig))329 .zip(genC.generate(random, config.edgeConfig))330 .zip(genD.generate(random, config.edgeConfig))331 .zip(genE.generate(random, config.edgeConfig))332 .zip(genF.generate(random, config.edgeConfig))333 .takeWhile { constraints.evaluate() }334 .forEach { (abcde, f) ->335 val (abcd, e) = abcde336 val (abc, d) = abcd337 val (ab, c) = abc338 val (a, b) = ab339 val shrinkfn = shrinkfn(a, b, c, d, e, f, property, config.shrinkingMode)340 config.listeners.forEach { it.beforeTest() }341 test(342 context,343 config,344 shrinkfn,345 listOf(a.value, b.value, c.value, d.value, e.value, f.value),346 listOf(347 genA.classifier,348 genB.classifier,349 genC.classifier,350 genD.classifier,351 genE.classifier,352 genF.classifier,353 ),354 random.seed355 ) {356 context.property(a.value, b.value, c.value, d.value, e.value, f.value)357 }358 config.listeners.forEach { it.afterTest() }359 }360 context.outputClassifications(6, config, random.seed)361 context.checkMaxSuccess(config, random.seed)362 return context363}364suspend fun <A, B, C, D, E, F, G> proptest(365 genA: Gen<A>,366 genB: Gen<B>,367 genC: Gen<C>,368 genD: Gen<D>,369 genE: Gen<E>,370 genF: Gen<F>,371 genG: Gen<G>,372 config: PropTestConfig,373 property: suspend PropertyContext.(A, B, C, D, E, F, G) -> Unit374): PropertyContext {375 config.checkFailOnSeed()376 val constraints = config.constraints377 ?: config.iterations?.let { Constraints.iterations(it) }378 ?: Constraints.iterations(PropertyTesting.defaultIterationCount)379 val context = PropertyContext()380 val random = createRandom(config)381 genA.generate(random, config.edgeConfig)382 .zip(genB.generate(random, config.edgeConfig))383 .zip(genC.generate(random, config.edgeConfig))384 .zip(genD.generate(random, config.edgeConfig))385 .zip(genE.generate(random, config.edgeConfig))386 .zip(genF.generate(random, config.edgeConfig))387 .zip(genG.generate(random, config.edgeConfig))388 .takeWhile { constraints.evaluate() }389 .forEach { (abcdef, g) ->390 val (abcde, f) = abcdef391 val (abcd, e) = abcde392 val (abc, d) = abcd393 val (ab, c) = abc394 val (a, b) = ab395 val shrinkfn = shrinkfn(a, b, c, d, e, f, g, property, config.shrinkingMode)396 config.listeners.forEach { it.beforeTest() }397 test(398 context,399 config,400 shrinkfn,401 listOf(a.value, b.value, c.value, d.value, e.value, f.value, g.value),402 listOf(403 genA.classifier,404 genB.classifier,405 genC.classifier,406 genD.classifier,407 genE.classifier,408 genF.classifier,409 genG.classifier410 ),411 random.seed412 ) {413 context.property(a.value, b.value, c.value, d.value, e.value, f.value, g.value)414 }415 config.listeners.forEach { it.afterTest() }416 }417 context.outputClassifications(7, config, random.seed)418 context.checkMaxSuccess(config, random.seed)419 return context420}421suspend fun <A, B, C, D, E, F, G, H> proptest(422 genA: Gen<A>,423 genB: Gen<B>,424 genC: Gen<C>,425 genD: Gen<D>,426 genE: Gen<E>,427 genF: Gen<F>,428 genG: Gen<G>,429 genH: Gen<H>,430 config: PropTestConfig,431 property: suspend PropertyContext.(A, B, C, D, E, F, G, H) -> Unit432): PropertyContext {433 config.checkFailOnSeed()434 val constraints = config.constraints435 ?: config.iterations?.let { Constraints.iterations(it) }436 ?: Constraints.iterations(PropertyTesting.defaultIterationCount)437 val context = PropertyContext()438 val random = createRandom(config)439 genA.generate(random, config.edgeConfig)440 .zip(genB.generate(random, config.edgeConfig))441 .zip(genC.generate(random, config.edgeConfig))442 .zip(genD.generate(random, config.edgeConfig))443 .zip(genE.generate(random, config.edgeConfig))444 .zip(genF.generate(random, config.edgeConfig))445 .zip(genG.generate(random, config.edgeConfig))446 .zip(genH.generate(random, config.edgeConfig))447 .takeWhile { constraints.evaluate() }448 .forEach { (abcdefg, h) ->449 val (abcdef, g) = abcdefg450 val (abcde, f) = abcdef451 val (abcd, e) = abcde452 val (abc, d) = abcd453 val (ab, c) = abc454 val (a, b) = ab455 val shrinkfn = shrinkfn(a, b, c, d, e, f, g, h, property, config.shrinkingMode)456 config.listeners.forEach { it.beforeTest() }457 test(458 context,459 config,460 shrinkfn,461 listOf(a.value, b.value, c.value, d.value, e.value, f.value, g.value, h.value),462 listOf(463 genA.classifier,464 genB.classifier,465 genC.classifier,466 genD.classifier,467 genE.classifier,468 genF.classifier,469 genG.classifier,470 genH.classifier471 ),472 random.seed473 ) {474 context.property(a.value, b.value, c.value, d.value, e.value, f.value, g.value, h.value)475 }476 config.listeners.forEach { it.afterTest() }477 }478 context.outputClassifications(8, config, random.seed)479 context.checkMaxSuccess(config, random.seed)480 return context481}482suspend fun <A, B, C, D, E, F, G, H, I> proptest(483 genA: Gen<A>,484 genB: Gen<B>,485 genC: Gen<C>,486 genD: Gen<D>,487 genE: Gen<E>,488 genF: Gen<F>,489 genG: Gen<G>,490 genH: Gen<H>,491 genI: Gen<I>,492 config: PropTestConfig,493 property: suspend PropertyContext.(A, B, C, D, E, F, G, H, I) -> Unit494): PropertyContext {495 config.checkFailOnSeed()496 val constraints = config.constraints497 ?: config.iterations?.let { Constraints.iterations(it) }498 ?: Constraints.iterations(PropertyTesting.defaultIterationCount)499 val context = PropertyContext()500 val random = createRandom(config)501 genA.generate(random, config.edgeConfig)502 .zip(genB.generate(random, config.edgeConfig))503 .zip(genC.generate(random, config.edgeConfig))504 .zip(genD.generate(random, config.edgeConfig))505 .zip(genE.generate(random, config.edgeConfig))506 .zip(genF.generate(random, config.edgeConfig))507 .zip(genG.generate(random, config.edgeConfig))508 .zip(genH.generate(random, config.edgeConfig))509 .zip(genI.generate(random, config.edgeConfig))510 .takeWhile { constraints.evaluate() }511 .forEach { (abcdefgh, i) ->512 val (abcdefg, h) = abcdefgh513 val (abcdef, g) = abcdefg514 val (abcde, f) = abcdef515 val (abcd, e) = abcde516 val (abc, d) = abcd517 val (ab, c) = abc518 val (a, b) = ab519 val shrinkfn = shrinkfn(a, b, c, d, e, f, g, h, i, property, config.shrinkingMode)520 config.listeners.forEach { it.beforeTest() }521 test(522 context,523 config,524 shrinkfn,525 listOf(a.value, b.value, c.value, d.value, e.value, f.value, g.value, h.value, i.value),526 listOf(527 genA.classifier,528 genB.classifier,529 genC.classifier,530 genD.classifier,531 genE.classifier,532 genF.classifier,533 genG.classifier,534 genH.classifier,535 genI.classifier536 ),537 random.seed538 ) {539 context.property(a.value, b.value, c.value, d.value, e.value, f.value, g.value, h.value, i.value)540 }541 config.listeners.forEach { it.afterTest() }542 }543 context.outputClassifications(9, config, random.seed)544 context.checkMaxSuccess(config, random.seed)545 return context546}547suspend fun <A, B, C, D, E, F, G, H, I, J> proptest(548 genA: Gen<A>,549 genB: Gen<B>,550 genC: Gen<C>,551 genD: Gen<D>,552 genE: Gen<E>,553 genF: Gen<F>,554 genG: Gen<G>,555 genH: Gen<H>,556 genI: Gen<I>,557 genJ: Gen<J>,558 config: PropTestConfig,559 property: suspend PropertyContext.(A, B, C, D, E, F, G, H, I, J) -> Unit560): PropertyContext {561 config.checkFailOnSeed()562 val constraints = config.constraints563 ?: config.iterations?.let { Constraints.iterations(it) }564 ?: Constraints.iterations(PropertyTesting.defaultIterationCount)565 val context = PropertyContext()566 val random = createRandom(config)567 genA.generate(random, config.edgeConfig)568 .zip(genB.generate(random, config.edgeConfig))569 .zip(genC.generate(random, config.edgeConfig))570 .zip(genD.generate(random, config.edgeConfig))571 .zip(genE.generate(random, config.edgeConfig))572 .zip(genF.generate(random, config.edgeConfig))573 .zip(genG.generate(random, config.edgeConfig))574 .zip(genH.generate(random, config.edgeConfig))575 .zip(genI.generate(random, config.edgeConfig))576 .zip(genJ.generate(random, config.edgeConfig))577 .takeWhile { constraints.evaluate() }578 .forEach { (abcdefghi, j) ->579 val (abcdefgh, i) = abcdefghi580 val (abcdefg, h) = abcdefgh581 val (abcdef, g) = abcdefg582 val (abcde, f) = abcdef583 val (abcd, e) = abcde584 val (abc, d) = abcd585 val (ab, c) = abc586 val (a, b) = ab587 val shrinkfn = shrinkfn(a, b, c, d, e, f, g, h, i, j, property, config.shrinkingMode)588 config.listeners.forEach { it.beforeTest() }589 test(590 context,591 config,592 shrinkfn,593 listOf(a.value, b.value, c.value, d.value, e.value, f.value, g.value, h.value, i.value, j.value),594 listOf(595 genA.classifier,596 genB.classifier,597 genC.classifier,598 genD.classifier,599 genE.classifier,600 genF.classifier,601 genG.classifier,602 genH.classifier,603 genI.classifier,604 genJ.classifier605 ),606 random.seed607 ) {608 context.property(a.value, b.value, c.value, d.value, e.value, f.value, g.value, h.value, i.value, j.value)609 }610 config.listeners.forEach { it.afterTest() }611 }612 context.outputClassifications(10, config, random.seed)613 context.checkMaxSuccess(config, random.seed)614 return context615}616suspend fun <A, B, C, D, E, F, G, H, I, J, K> proptest(617 genA: Gen<A>,618 genB: Gen<B>,619 genC: Gen<C>,620 genD: Gen<D>,621 genE: Gen<E>,622 genF: Gen<F>,623 genG: Gen<G>,624 genH: Gen<H>,625 genI: Gen<I>,626 genJ: Gen<J>,627 genK: Gen<K>,628 config: PropTestConfig,629 property: suspend PropertyContext.(A, B, C, D, E, F, G, H, I, J, K) -> Unit630): PropertyContext {631 config.checkFailOnSeed()632 val constraints = config.constraints633 ?: config.iterations?.let { Constraints.iterations(it) }634 ?: Constraints.iterations(PropertyTesting.defaultIterationCount)635 val context = PropertyContext()636 val random = createRandom(config)637 genA.generate(random, config.edgeConfig)638 .zip(genB.generate(random, config.edgeConfig))639 .zip(genC.generate(random, config.edgeConfig))640 .zip(genD.generate(random, config.edgeConfig))641 .zip(genE.generate(random, config.edgeConfig))642 .zip(genF.generate(random, config.edgeConfig))643 .zip(genG.generate(random, config.edgeConfig))644 .zip(genH.generate(random, config.edgeConfig))645 .zip(genI.generate(random, config.edgeConfig))646 .zip(genJ.generate(random, config.edgeConfig))647 .zip(genK.generate(random, config.edgeConfig))648 .takeWhile { constraints.evaluate() }649 .forEach { (abcdefghij, k) ->650 val (abcdefghi, j) = abcdefghij651 val (abcdefgh, i) = abcdefghi652 val (abcdefg, h) = abcdefgh653 val (abcdef, g) = abcdefg654 val (abcde, f) = abcdef655 val (abcd, e) = abcde656 val (abc, d) = abcd657 val (ab, c) = abc658 val (a, b) = ab659 val shrinkfn = shrinkfn(a, b, c, d, e, f, g, h, i, j, k, property, config.shrinkingMode)660 config.listeners.forEach { it.beforeTest() }661 test(662 context,663 config,664 shrinkfn,665 listOf(a.value, b.value, c.value, d.value, e.value, f.value, g.value, h.value, i.value, j.value, k.value),666 listOf(667 genA.classifier,668 genB.classifier,669 genC.classifier,670 genD.classifier,671 genE.classifier,672 genF.classifier,673 genG.classifier,674 genH.classifier,675 genI.classifier,676 genJ.classifier,677 genK.classifier678 ),679 random.seed680 ) {681 context.property(682 a.value,683 b.value,684 c.value,685 d.value,686 e.value,687 f.value,688 g.value,689 h.value,690 i.value,691 j.value,692 k.value693 )694 }695 config.listeners.forEach { it.afterTest() }696 }697 context.outputClassifications(11, config, random.seed)698 context.checkMaxSuccess(config, random.seed)699 return context700}701suspend fun <A, B, C, D, E, F, G, H, I, J, K, L> proptest(702 genA: Gen<A>,703 genB: Gen<B>,704 genC: Gen<C>,705 genD: Gen<D>,706 genE: Gen<E>,707 genF: Gen<F>,708 genG: Gen<G>,709 genH: Gen<H>,710 genI: Gen<I>,711 genJ: Gen<J>,712 genK: Gen<K>,713 genL: Gen<L>,714 config: PropTestConfig,715 property: suspend PropertyContext.(A, B, C, D, E, F, G, H, I, J, K, L) -> Unit716): PropertyContext {717 config.checkFailOnSeed()718 val constraints = config.constraints719 ?: config.iterations?.let { Constraints.iterations(it) }720 ?: Constraints.iterations(PropertyTesting.defaultIterationCount)721 val context = PropertyContext()722 val random = createRandom(config)723 genA.generate(random, config.edgeConfig)724 .zip(genB.generate(random, config.edgeConfig))725 .zip(genC.generate(random, config.edgeConfig))726 .zip(genD.generate(random, config.edgeConfig))727 .zip(genE.generate(random, config.edgeConfig))728 .zip(genF.generate(random, config.edgeConfig))729 .zip(genG.generate(random, config.edgeConfig))730 .zip(genH.generate(random, config.edgeConfig))731 .zip(genI.generate(random, config.edgeConfig))732 .zip(genJ.generate(random, config.edgeConfig))733 .zip(genK.generate(random, config.edgeConfig))734 .zip(genL.generate(random, config.edgeConfig))735 .takeWhile { constraints.evaluate() }736 .forEach { (abcdefghijk, l) ->737 val (abcdefghij, k) = abcdefghijk738 val (abcdefghi, j) = abcdefghij739 val (abcdefgh, i) = abcdefghi740 val (abcdefg, h) = abcdefgh741 val (abcdef, g) = abcdefg742 val (abcde, f) = abcdef743 val (abcd, e) = abcde744 val (abc, d) = abcd745 val (ab, c) = abc746 val (a, b) = ab747 val shrinkfn = shrinkfn(a, b, c, d, e, f, g, h, i, j, k, l, property, config.shrinkingMode)748 config.listeners.forEach { it.beforeTest() }749 test(750 context,751 config,752 shrinkfn,753 listOf(754 a.value,755 b.value,756 c.value,757 d.value,758 e.value,759 f.value,760 g.value,761 h.value,762 i.value,763 j.value,764 k.value,765 l.value766 ),767 listOf(768 genA.classifier,769 genB.classifier,770 genC.classifier,771 genD.classifier,772 genE.classifier,773 genF.classifier,774 genG.classifier,775 genH.classifier,776 genI.classifier,777 genJ.classifier,778 genK.classifier,779 genL.classifier780 ),781 random.seed782 ) {783 context.property(784 a.value,785 b.value,786 c.value,787 d.value,788 e.value,789 f.value,790 g.value,791 h.value,792 i.value,793 j.value,794 k.value,795 l.value796 )797 }798 config.listeners.forEach { it.afterTest() }799 }800 context.outputClassifications(12, config, random.seed)801 context.checkMaxSuccess(config, random.seed)802 return context803}...

Full Screen

Full Screen

HelperMethodsTest.kt

Source:HelperMethodsTest.kt Github

copy

Full Screen

1package io.github.ricardorlg.devicefarm.tractor.utils2import io.github.ricardorlg.devicefarm.tractor.model.*3import io.github.ricardorlg.devicefarm.tractor.utils.HelperMethods.uploadType4import io.github.ricardorlg.devicefarm.tractor.utils.HelperMethods.validateFileExtensionByType5import io.kotest.assertions.arrow.core.shouldBeLeft6import io.kotest.assertions.arrow.core.shouldBeRight7import io.kotest.core.spec.style.StringSpec8import io.kotest.engine.spec.tempfile9import io.kotest.matchers.should10import io.kotest.matchers.shouldBe11import io.kotest.matchers.throwable.shouldHaveMessage12import io.kotest.matchers.types.shouldBeInstanceOf13import io.kotest.property.Exhaustive14import io.kotest.property.checkAll15import io.kotest.property.exhaustive.collection16import software.amazon.awssdk.services.devicefarm.model.UploadType17class HelperMethodsTest : StringSpec({18 "When Android upload type is used, file must end with .apk" {19 //GIVEN20 val file = tempfile("testFile", ".apk")21 //WHEN22 val response = file.validateFileExtensionByType(UploadType.ANDROID_APP)23 //THEN24 response.shouldBeRight() shouldBe file25 }26 "When Android upload type is used, and file does not have .apk extension an error is returned" {27 //GIVEN28 val file = tempfile("testFile")29 val expectedErrorMessage =30 "the file ${file.nameWithoutExtension} is not a valid Android app. It should has .apk extension"31 //WHEN32 val response = file.validateFileExtensionByType(UploadType.ANDROID_APP)33 //THEN34 response.shouldBeLeft() should {35 it.shouldBeInstanceOf<DeviceFarmIllegalArtifactExtension>()36 it shouldHaveMessage expectedErrorMessage37 it.cause.shouldBeInstanceOf<IllegalArgumentException>()38 }39 }40 "When IOS upload type is used, file must end with .ipa" {41 //GIVEN42 val file = tempfile("testFile", ".ipa")43 //WHEN44 val response = file.validateFileExtensionByType(UploadType.IOS_APP)45 //THEN46 response.shouldBeRight() shouldBe file47 }48 "When IOS upload type is used, and file does not have .ipa extension an error is returned" {49 //GIVEN50 val file = tempfile("testFile")51 val expectedErrorMessage =52 "the file ${file.nameWithoutExtension} is not a valid IOS app. It should has .ipa extension"53 //WHEN54 val response = file.validateFileExtensionByType(UploadType.IOS_APP)55 //THEN56 response.shouldBeLeft() should {57 it.shouldBeInstanceOf<DeviceFarmIllegalArtifactExtension>()58 it shouldHaveMessage expectedErrorMessage59 it.cause.shouldBeInstanceOf<IllegalArgumentException>()60 }61 }62 "When Appium Node Test Spec upload type is used, file must end with .yml" {63 //GIVEN64 val file = tempfile("testFile", ".yml")65 //WHEN66 val response = file.validateFileExtensionByType(UploadType.APPIUM_NODE_TEST_SPEC)67 //THEN68 response.shouldBeRight() shouldBe file69 }70 "When Appium Node Test Spec upload type is used, and file does not have .yml extension an error is returned" {71 //GIVEN72 val file = tempfile("testFile")73 val expectedErrorMessage =74 "the file ${file.nameWithoutExtension} is not a valid test spec file. It should has .yml extension"75 //WHEN76 val response = file.validateFileExtensionByType(UploadType.APPIUM_NODE_TEST_SPEC)77 //THEN78 response.shouldBeLeft() should {79 it.shouldBeInstanceOf<DeviceFarmIllegalArtifactExtension>()80 it shouldHaveMessage expectedErrorMessage81 it.cause.shouldBeInstanceOf<IllegalArgumentException>()82 }83 }84 "When Upload type is not Android,IOS or Appium, the file must have .zip extension" {85 //GIVEN86 val file = tempfile("testFile", ".zip")87 //WHEN88 val response = file.validateFileExtensionByType(UploadType.WEB_APP)89 //THEN90 response.shouldBeRight() shouldBe file91 }92 "When Upload type is not Android,IOS or Appium, and file does not have .zip extension an error is returned" {93 //GIVEN94 val file = tempfile("testFile")95 val expectedErrorMessage =96 "the file ${file.nameWithoutExtension} is not a valid general file. It should has .zip extension"97 //WHEN98 val response = file.validateFileExtensionByType(UploadType.WEB_APP)99 //THEN100 response.shouldBeLeft() should {101 it.shouldBeInstanceOf<DeviceFarmIllegalArtifactExtension>()102 it shouldHaveMessage expectedErrorMessage103 it.cause.shouldBeInstanceOf<IllegalArgumentException>()104 }105 }106 "When unknown Upload type is used, an error should be returned"{107 //WHEN108 val response = tempfile().validateFileExtensionByType(UploadType.UNKNOWN_TO_SDK_VERSION)109 //THEN110 response.shouldBeLeft() should {111 it.shouldBeInstanceOf<DeviceFarmIllegalArtifactExtension.UnsupportedException>()112 it.cause.shouldBeInstanceOf<IllegalArgumentException>()113 }114 }115 "When loading a file from a given path, it should return it as a right" {116 //GIVEN117 val expectedFile = tempfile("testFile")118 //WHEN119 val response = HelperMethods.loadFileFromPath(expectedFile.path)120 //THEN121 response.shouldBeRight() shouldBe expectedFile122 }123 "When loading a file from a given path, if the files doesn't exists an error should be returned as a Left" {124 //WHEN125 val path = "path/to/non_existing/file"126 val response = HelperMethods.loadFileFromPath(path)127 //THEN128 response.shouldBeLeft() should {129 it.shouldBeInstanceOf<DeviceFarmTractorGeneralError>()130 it shouldHaveMessage "The file at $path does not exists"131 it.cause.shouldBeInstanceOf<java.lang.IllegalArgumentException>()132 }133 }134 "When no path is provided an Illegal Argument error should be returned as a left " {135 //WHEN136 val response = HelperMethods.loadFileFromPath(" ")137 //THEN138 response.shouldBeLeft() should {139 it.shouldBeInstanceOf<DeviceFarmTractorErrorIllegalArgumentException>()140 }141 }142 "When no path is provided getting the upload type of a path, an Illegal Argument error should be returned as a left"{143 //WHEN144 val response = " ".uploadType()145 //THEN146 response.shouldBeLeft() should {147 it.shouldBeInstanceOf<DeviceFarmTractorErrorIllegalArgumentException>()148 it shouldHaveMessage MANDATORY_PATH_PARAMETER149 }150 }151 "When getting the upload type of an unsupported file, an Illegal Argument error should be returned as a left"{152 //GIVEN153 val app = tempfile("testApp", ".zip")154 //WHEN155 val response = app.path.uploadType()156 //THEN157 response.shouldBeLeft() should {158 it.shouldBeInstanceOf<DeviceFarmTractorErrorIllegalArgumentException>()159 it shouldHaveMessage UNSUPPORTED_APP_FILE_EXTENSION.format(app.extension)160 }161 }162 "When getting the upload type of a valid file, it should return it as a right"{163 checkAll(164 Exhaustive.collection(165 listOf(166 ".apk" to UploadType.ANDROID_APP,167 ".ipa" to UploadType.IOS_APP168 )169 )170 ) { (extension, expectedUploadType) ->171 //GIVEN172 val app = tempfile("testApp", extension)173 //WHEN174 val response = app.path.uploadType()175 //THEN176 response.shouldBeRight() shouldBe expectedUploadType177 }178 }179})...

Full Screen

Full Screen

StringCalculatorKataPBTTest.kt

Source:StringCalculatorKataPBTTest.kt Github

copy

Full Screen

1import arrow.core.left2import arrow.core.right3import io.kotest.core.Tuple34import io.kotest.core.spec.style.FunSpec5import io.kotest.matchers.shouldBe6import io.kotest.property.Arb7import io.kotest.property.Exhaustive8import io.kotest.property.arbitrary.*9import io.kotest.property.checkAll10import io.kotest.property.exhaustive.azstring11class StringCalculatorKataPBTTest : FunSpec({12 val defaultDelimiters = Arb.element(",", "\n")13 val validValues = Arb.positiveInts(1000)14 context("step1") {15 test("should return 0 on empty string") {16 add("") shouldBe 0.right()17 }18 test("should return the value on single number") {19 validValues.checkAll { a -> add("$a") shouldBe a.right() }20 }21 test("should return the sum of two numbers") {22 Arb.bind(23 validValues,24 validValues,25 ::Pair26 ).checkAll { (a, b) -> add("$a,$b") shouldBe (a + b).right() }27 }28 test("should result InvalidNumber on a invalid int string") {29 Exhaustive.azstring(1..100).checkAll { x ->30 add(x) shouldBe InvalidNumbersError(listOf(x)).left()31 }32 }33 }34 context("step2") {35 test("should return the sum of any size of numbers") {36 Arb.list(validValues).checkAll { x ->37 add(x.joinToString(",")) shouldBe x.sum().right()38 }39 }40 test("should result InvalidNumber on the first invalid int string") {41 Arb.bind(42 validValues,43 Exhaustive.azstring(1..2),44 validValues,45 ::Tuple346 ).checkAll { (x, y, z) ->47 add("$x, $y,$z") shouldBe InvalidNumbersError(listOf(y)).left()48 }49 }50 }51 context("step3") {52 test("should accept , and endline as number separator") {53 Arb.bind(54 validValues,55 validValues,56 defaultDelimiters,57 ::Tuple358 ).checkAll { (x, y, separator) ->59 add("$x$separator$y") shouldBe (x + y).right()60 }61 }62 test("should not accept a string ending with a delimiter") {63 Arb.bind(64 Arb.list(validValues, 1..100),65 Arb.list(defaultDelimiters, 1..100)66 ) { values, separators ->67 values.zip(separators).joinToString { (x, y) -> "$x$y" }68 }.checkAll { x ->69 add(x) shouldBe StartingOrEndingByDelimiter.left()70 }71 }72 test("should not accept a string starting with a delimiter") {73 Arb.bind(74 Arb.list(validValues, 1..100),75 Arb.list(defaultDelimiters, 1..100)76 ) { values, separators ->77 values.zip(separators).joinToString { (x, y) -> "$y$x" }78 }.checkAll { x ->79 add(x) shouldBe StartingOrEndingByDelimiter.left()80 }81 }82 }83 context("step4") {84 test("should be able to define a delimiter") {85 Arb.bind(86 Arb.element(";", "/"),87 Arb.list(validValues),88 ::Pair89 ).checkAll { (newDelimiter, values) ->90 add("//[$newDelimiter]\n${values.joinToString(newDelimiter)}") shouldBe values.sum().right()91 }92 }93 }94 context("step5") {95 test("should not accept negative integers") {96 Arb.negativeInts().checkAll { add("$it") shouldBe NegativeInteger(listOf(it)).left() }97 Arb.bind(98 Arb.negativeInts(),99 Arb.list(validValues),100 defaultDelimiters,101 ) { invalidValue, validValues, delimiter ->102 invalidValue to (validValues + invalidValue).shuffled().map{ it.toString()}.reduce { x, y -> "$x$delimiter$y"}103 }.checkAll { (invalidValue, value) ->104 add(value) shouldBe NegativeInteger(listOf(invalidValue)).left()105 }106 }107 test("should accumulate all negative integers") {108 Arb.negativeInts().checkAll { add("$it") shouldBe NegativeInteger(listOf(it)).left() }109 Arb.bind(110 Arb.list(Arb.negativeInts(),1..100),111 Arb.list(validValues),112 defaultDelimiters,113 ) { invalidValues, validValues, delimiter ->114 invalidValues to (validValues + invalidValues).shuffled().map{ it.toString()}.reduce { x, y -> "$x$delimiter$y"}115 }.checkAll { (invalidValues, value) ->116 // Should import kotest assert for arrow instead of forcing order117 add(value).mapLeft { NegativeInteger((it as NegativeInteger).values.sorted()) } shouldBe NegativeInteger(invalidValues.sorted()).left()118 }119 }120 }121 context("step6") {122 test("should skip values > 1000") {123 Arb.list(Arb.positiveInts(3000)).checkAll { values ->124 add(values.joinToString(defaultDelimiters.next())) shouldBe values.filter { it <= 1000 }.sum().right()125 }126 }127 }128 context("step7") {129 test("should be able to define a delimiter with multiple characters") {130 Arb.bind(131 Arb.element("***", "__", "---"),132 Arb.list(validValues),133 ::Pair134 ).checkAll { (newDelimiter, values) ->135 add("//[$newDelimiter]\n${values.joinToString(newDelimiter)}") shouldBe values.sum().right()136 }137 }138 }139 context("step8") {140 test("should be able to define multiple delimiters") {141 Arb.bind(142 Arb.list(Arb.element("*", "_", "-"), 1..10),143 Arb.list(validValues, 1..100),144 ::Pair145 ).checkAll { (newDelimiters, values) ->146 val valueString = "//${newDelimiters.joinToString("") { "[$it]" }}\n${values.map{it.toString()}.reduce { x, y -> "$x${newDelimiters.random()}$y" }}"147 println("Test $valueString")148 add(valueString) shouldBe values.sum().right()149 }150 }151 }152 context("step9") {153 test("should be able to define multiple delimiters with multiple characters") {154 Arb.bind(155 Arb.list(Arb.element("***", "__", "---"), 1..10),156 Arb.list(validValues, 1..100),157 ::Pair158 ).checkAll { (newDelimiters, values) ->159 val valueString = "//${newDelimiters.joinToString("") { "[$it]" }}\n${values.map{it.toString()}.reduce { x, y -> "$x${newDelimiters.random()}$y" }}"160 println("Test $valueString")161 add(valueString) shouldBe values.sum().right()162 }163 }164 }165})...

Full Screen

Full Screen

Exhaustive.kt

Source:Exhaustive.kt Github

copy

Full Screen

1package io.kotest.property.exhaustive2import io.kotest.property.Arb3import io.kotest.property.Exhaustive4import kotlin.jvm.JvmName5/**6 * Returns an [Exhaustive] which provides the values from the given list.7 * @param `as` a non empty list.8 * @return [Exhaustive]9 * @throws [IllegalArgumentException] if the `as` is a empty list.10 */11fun <A> exhaustive(`as`: List<A>): Exhaustive<A> = `as`.exhaustive()12fun <A> Exhaustive.Companion.of(vararg elements: A): Exhaustive<A> = Exhaustive.collection(elements.asList())13/**14 * Returns an [Exhaustive] which provides the values from the receiver.15 * @return [Exhaustive]16 * @throws [IllegalArgumentException] if the receiver is a empty list.17 */18@JvmName("exhaustiveExt")19fun <A> List<A>.exhaustive(): Exhaustive<A> {20 require(this.isNotEmpty()) { "Can't build a Exhaustive for a empty list." }21 return object : Exhaustive<A>() {22 override val values = this@exhaustive23 }24}25/**26 * Returns a new [Exhaustive] which will merge the values from this Exhaustive and the values of27 * the supplied Exhaustive together, taking one from each in turn.28 *29 * In other words, if genA provides 1,2,3 and genB provides 7,8,9 then the merged30 * gen would output 1,7,2,8,3,9.31 *32 * The supplied gen and this gen must have a common supertype.33 *34 * @param other the arg to merge with this one35 * @return the merged arg.36 */37fun <A, B : A, C : A> Exhaustive<B>.merge(other: Exhaustive<C>): Exhaustive<A> = object : Exhaustive<A>() {38 override val values: List<A> = this@merge.values.zip(other.values).flatMap { listOf(it.first, it.second) }39}40/**41 * Returns a new [Exhaustive] which takes its elements from the receiver and filters42 * them using the supplied predicate.43 * In other words this exhaustive is a subset of the elements as determined by the filter.44 */45fun <A> Exhaustive<A>.filter(predicate: (A) -> Boolean) = object : Exhaustive<A>() {46 override val values: List<A> =47 this@filter.values.filter { predicate(it) }48}49/**50 * @return a new [Exhaustive] by filtering this Exhaustives output by the negated function [f]51 */52fun <A> Exhaustive<A>.filterNot(f: (A) -> Boolean): Exhaustive<A> = filter { !f(it) }53/**54 * Returns a new [Exhaustive] which takes its elements from the receiver and maps them using the supplied function.55 */56fun <A, B> Exhaustive<A>.map(f: (A) -> B): Exhaustive<B> = object : Exhaustive<B>() {57 override val values: List<B> =58 this@map.values.map { f(it) }59}60/**61 * Returns a new [Exhaustive] which takes its elements from the receiver and maps them using the supplied function.62 */63fun <A, B> Exhaustive<A>.flatMap(f: (A) -> Exhaustive<B>): Exhaustive<B> = object : Exhaustive<B>() {64 override val values: List<B> =65 this@flatMap.values.flatMap { f(it).values }66}67/**68 * Wraps a [Exhaustive] lazily. The given [f] is only evaluated once,69 * and not until the wrapper [Exhaustive] is evaluated.70 * */71fun <A> Exhaustive.Companion.lazy(f: () -> Exhaustive<A>): Exhaustive<A> {72 return object : Exhaustive<A>() {73 override val values: List<A> by kotlin.lazy { f().values }74 }75}...

Full Screen

Full Screen

strings.kt

Source:strings.kt Github

copy

Full Screen

1package io.kotest.property.exhaustive2import io.kotest.property.Exhaustive3fun Exhaustive.Companion.azstring(range: IntRange): Exhaustive<String> {4 fun az() = ('a'..'z').map { it.toString() }5 val values = range.toList().flatMap { size ->6 List(size) { az() }.reduce { acc, seq -> acc.zip(seq).map { (a, b) -> a + b } }7 }8 return values.exhaustive()9}...

Full Screen

Full Screen

zip.kt

Source:zip.kt Github

copy

Full Screen

1package io.kotest.property.exhaustive2import io.kotest.property.Exhaustive3fun <A, B> Exhaustive<A>.zip(other: Exhaustive<B>): Exhaustive<Pair<A, B>> {4 return this.values.zip(other.values).exhaustive()5}...

Full Screen

Full Screen

Automation Testing Tutorials

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.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Kotest automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Most used method in zip

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful