Best Kotest code snippet using io.kotest.core.names.DisplayNameFormatter.format
JUnitTestEngineListener.kt
Source:JUnitTestEngineListener.kt
...74 private val listener: EngineExecutionListener,75 val root: EngineDescriptor,76) : AbstractTestEngineListener() {77 private val logger = Logger(JUnitTestEngineListener::class)78 private var formatter: DisplayNameFormatter = DefaultDisplayNameFormatter(ProjectConfiguration())79 // contains a mapping of junit TestDescriptor's, so we can find previously registered tests80 private val descriptors = mutableMapOf<Descriptor, TestDescriptor>()81 private var started = false82 private val startedTests = mutableSetOf<Descriptor.TestDescriptor>()83 // the root tests are our entry point when outputting results84 private val rootTests = mutableListOf<TestCase>()85 private var failOnIgnoredTests = false86 private val children = mutableMapOf<Descriptor, MutableList<TestCase>>()87 private val results = mutableMapOf<Descriptor, TestResult>()88 private val dummies = hashSetOf<String>()89 override suspend fun engineStarted() {90 logger.log { Pair(null, "Engine started") }91 listener.executionStarted(root)92 }93 override suspend fun engineInitialized(context: EngineContext) {94 failOnIgnoredTests = context.configuration.failOnIgnoredTests95 formatter = getDisplayNameFormatter(context.configuration.registry, context.configuration)96 }97 override suspend fun engineFinished(t: List<Throwable>) {98 logger.log { Pair(null, "Engine finished; throwables=[${t}]") }99 registerExceptionPlaceholders(t)100 val result = if (failOnIgnoredTests && results.values.any { it.isIgnored }) {101 TestExecutionResult.failed(RuntimeException("Build contained ignored test"))102 } else {103 TestExecutionResult.successful()104 }105 logger.log { Pair(null, "Notifying junit that engine completed $root") }106 listener.executionFinished(root, result)107 }108 override suspend fun specStarted(kclass: KClass<*>) {109 markSpecStarted(kclass)110 }111 override suspend fun specFinished(kclass: KClass<*>, result: TestResult) {112 val t = result.errorOrNull113 when {114 // if we have a spec error before we even started the spec, we will start the spec, add a placeholder115 // to hold the error, mark that test as failed, and then fail the spec as well116 t != null && !started -> {117 val descriptor = markSpecStarted(kclass)118 addPlaceholderTest(descriptor, t, kclass)119 logger.log { Pair(kclass.bestName(), "execution failed: $descriptor $t") }120 listener.executionFinished(descriptor, TestExecutionResult.failed(t))121 }122 // if we had an error in the spec, and we had no tests, we'll add the dummy and return123 t != null && rootTests.isEmpty() -> {124 val descriptor = getSpecDescriptor(kclass)125 addPlaceholderTest(descriptor, t, kclass)126 logger.log { Pair(kclass.bestName(), "execution failed: $descriptor $t") }127 listener.executionFinished(descriptor, TestExecutionResult.failed(t))128 }129 else -> {130 val descriptor = getSpecDescriptor(kclass)131 val result = when (t) {132 null -> TestExecutionResult.successful()133 else -> {134 addPlaceholderTest(descriptor, t, kclass)135 TestExecutionResult.successful()136 }137 }138 logger.log { Pair(kclass.bestName(), "executionFinished: $descriptor") }139 listener.executionFinished(descriptor, result)140 }141 }142 reset()143 }144 override suspend fun specIgnored(kclass: KClass<*>, reason: String?) {145 logger.log { Pair(kclass.bestName(), "Spec is being flagged as ignored") }146 listener.executionSkipped(getSpecDescriptor(kclass), reason)147 }148 private fun markSpecStarted(kclass: KClass<*>): TestDescriptor {149 return try {150 val descriptor = getSpecDescriptor(root, kclass.toDescriptor(), formatter.format(kclass))151 logger.log { Pair(kclass.bestName(), "Registering dynamic spec $descriptor") }152 listener.dynamicTestRegistered(descriptor)153 logger.log { Pair(kclass.bestName(), "Spec executionStarted $descriptor") }154 listener.executionStarted(descriptor)155 started = true156 descriptor157 } catch (t: Throwable) {158 logger.log { Pair(kclass.bestName(), "Error in JUnit Platform listener $t") }159 throw t160 }161 }162 private fun reset() {163 rootTests.clear()164 children.clear()165 results.clear()166 started = false167 descriptors.clear()168 startedTests.clear()169 }170 private fun addPlaceholderTest(parent: TestDescriptor, t: Throwable, kclass: KClass<*>) {171 val (name, cause) = ExtensionExceptionExtractor.resolve(t)172 val descriptor = createTestDescriptor(173 parent.uniqueId.append(Segment.Test.value, name),174 name,175 TestDescriptor.Type.TEST,176 ClassSource.from(kclass.java),177 false178 )179 parent.addChild(descriptor)180 listener.dynamicTestRegistered(descriptor)181 listener.executionStarted(descriptor)182 listener.executionFinished(descriptor, TestResult.Error(Duration.ZERO, cause).toTestExecutionResult())183 }184 override suspend fun testStarted(testCase: TestCase) {185 // depending on the test type, we may want to wait to notify junit, this is because gradle doesn't work186 // properly with the junit test types. Ideally, we'd just set everything to CONTAINER_AND_TEST, which is187 // supposed to mean a test can contain other tests as well as being a test itself, which is exactly how188 // Kotest views tests, but unfortunately it doesn't work properly.189 //190 // Another approach is to wait until the spec finishes to see which tests contain children and which191 // don't and set the test type appropriately, but junit doesn't give us a way to specify test duration192 // (instead it just calculates it itself from the time between marking a test as started and marking193 // it as finished), so this approach works but ends up having all tests as 0ms194 //195 // So the approach we will take is use the TestType from the test definition, unless it is dynamic,196 // then for dynamic we will calculate it later, and accept the 0ms drawback197 logger.log { Pair(testCase.name.testName, "test started") }198 if (testCase.parent != null) rootTests.add(testCase)199 addChild(testCase)200 when (testCase.type) {201 TestType.Container -> startTestIfNotStarted(testCase, TestDescriptor.Type.CONTAINER)202 TestType.Test -> startTestIfNotStarted(testCase, TestDescriptor.Type.TEST)203 TestType.Dynamic -> Unit204 }205 }206 // this test can be output now it has completed as we have all we need to know to complete it207 override suspend fun testFinished(testCase: TestCase, result: TestResult) {208 logger.log { Pair(testCase.name.testName, "test finished $result") }209 results[testCase.descriptor] = result210 val descriptor = getOrCreateTestDescriptor(testCase, null)211 // we need to ensure all parents have been started first212 startParents(testCase)213 startTestIfNotStarted(testCase, null)214 logger.log { Pair(testCase.name.testName, "executionFinished: $descriptor") }215 listener.executionFinished(descriptor, result.toTestExecutionResult())216 }217 override suspend fun testIgnored(testCase: TestCase, reason: String?) {218 logger.log { Pair(testCase.name.testName, "test ignored $reason") }219 if (testCase.parent == null) rootTests.add(testCase)220 addChild(testCase)221 results[testCase.descriptor] = TestResult.Ignored(reason)222 // we need to ensure all parents have been started first223 startParents(testCase)224 val descriptor = getOrCreateTestDescriptor(testCase, TestDescriptor.Type.TEST)225 logger.log { Pair(testCase.name.testName, "Registering dynamic test: $descriptor") }226 listener.dynamicTestRegistered(descriptor)227 logger.log { Pair(testCase.name.testName, "executionSkipped: $descriptor") }228 listener.executionSkipped(descriptor, reason)229 }230 private fun addChild(testCase: TestCase) {231 children.getOrPut(testCase.descriptor.parent) { mutableListOf() }.add(testCase)232 }233 private fun startParents(testCase: TestCase) {234 val parent = testCase.parent235 if (parent != null) {236 startParents(parent)237 startTestIfNotStarted(parent, null)238 }239 }240 private fun startTestIfNotStarted(testCase: TestCase, type: TestDescriptor.Type?) {241 if (!startedTests.contains(testCase.descriptor)) {242 val descriptor = getOrCreateTestDescriptor(testCase, type)243 logger.log { Pair(testCase.name.testName, "Registering dynamic test: $descriptor") }244 listener.dynamicTestRegistered(descriptor)245 logger.log { Pair(testCase.name.testName, "executionStarted: $descriptor") }246 listener.executionStarted(descriptor)247 startedTests.add(testCase.descriptor)248 }249 }250 private fun getOrCreateTestDescriptor(testCase: TestCase, type: TestDescriptor.Type?): TestDescriptor {251 val existing = descriptors[testCase.descriptor]252 if (existing != null) return existing253 val parent = when (val p = testCase.parent) {254 null -> getSpecDescriptor(testCase.spec::class)255 else -> getOrCreateTestDescriptor(p, null)256 }257 val id = parent.uniqueId.append(testCase.descriptor)258 // we dynamically work out the type if null by looking to see if this test had any children259 val c = children[testCase.descriptor]260 val t = when {261 type != null -> type262 c == null || c.isEmpty() -> TestDescriptor.Type.TEST263 else -> TestDescriptor.Type.CONTAINER264 }265 return createTestDescriptor(266 id,267 formatter.format(testCase),268 t,269 ClassSource.from(testCase.spec::class.java, null), // gradle-junit-platform hides tests if we don't send this270 type == TestDescriptor.Type.CONTAINER271 ).apply {272 parent.addChild(this)273 descriptors[testCase.descriptor] = this274 }275 }276 private fun getSpecDescriptor(kclass: KClass<*>): TestDescriptor {277 return getSpecDescriptor(root, kclass.toDescriptor(), formatter.format(kclass))278 }279 private fun createAndRegisterDummySpec(name: String): TestDescriptor {280 val unique = UniqueNames.unique(name, dummies) { s, k -> "${s}_$k" } ?: name281 dummies.add(unique)282 val descriptor = getSpecDescriptor(root, Descriptor.SpecDescriptor(DescriptorId(unique), this::class), unique)283 listener.dynamicTestRegistered(descriptor)284 return descriptor285 }286 private fun registerExceptionPlaceholders(ts: List<Throwable>) {287 ts.forEach {288 val (name, cause) = ExtensionExceptionExtractor.resolve(it)289 val container = createAndRegisterDummySpec(name)290 listener.executionStarted(container)291 listener.executionFinished(container, TestExecutionResult.failed(cause))...
TeamCityTestEngineListener.kt
Source:TeamCityTestEngineListener.kt
...21class TeamCityTestEngineListener(22 private val prefix: String = TeamCityMessageBuilder.TeamCityPrefix,23 private val details: Boolean = true,24) : TestEngineListener {25 private var formatter: DisplayNameFormatter = DefaultDisplayNameFormatter(ProjectConfiguration())26 // once a spec has completed, we want to be able to check whether any given test is27 // a container or a leaf test, and so this map contains all test that have children28 private val children = mutableMapOf<Descriptor, MutableList<TestCase>>()29 private val results = mutableMapOf<Descriptor, TestResult>()30 private val started = mutableSetOf<Descriptor.TestDescriptor>()31 // intellij has no method for failed suites, so if a container or spec fails we must insert32 // a dummy "test" in order to tag the error against that33 private fun insertPlaceholder(t: Throwable, parent: Descriptor) {34 val (name, cause) = ExtensionExceptionExtractor.resolve(t)35 val msg1 = TeamCityMessageBuilder36 .testStarted(prefix, name)37 .id(name)38 .parent(parent.path().value)39 .build()40 println(msg1)41 // we must print out the stack trace in between the dummy, so it appears when you click on the test name42 //t?.printStackTrace()43 val msg2 = TeamCityMessageBuilder44 .testFailed(prefix, name)45 .id(name)46 .parent(parent.path().value)47 .withException(cause, details)48 .build()49 println(msg2)50 val msg3 = TeamCityMessageBuilder51 .testFinished(prefix, name)52 .id(name)53 .parent(parent.path().value)54 .build()55 println(msg3)56 }57 override suspend fun engineStarted() {}58 override suspend fun engineInitialized(context: EngineContext) {59 formatter = getDisplayNameFormatter(context.configuration.registry, context.configuration)60 }61 override suspend fun engineFinished(t: List<Throwable>) {62 if (t.isNotEmpty()) {63 t.withIndex().forEach { (index, error) ->64 val testName = if (t.size == 1) "Engine exception" else "Engine exception ${index + 1}"65 println(TeamCityMessageBuilder.testStarted(prefix, testName).build())66 val message = error.message ?: t::class.bestName()67 println(TeamCityMessageBuilder.testFailed(prefix, testName).message(message).build())68 println(TeamCityMessageBuilder.testFinished(prefix, testName).build())69 }70 }71 }72 override suspend fun specStarted(kclass: KClass<*>) {73 val msg = TeamCityMessageBuilder74 .testSuiteStarted(prefix, formatter.format(kclass))75 .id(kclass.toDescriptor().path().value)76 .locationHint(Locations.location(kclass))77 .build()78 println(msg)79 }80 // ignored specs are completely hidden from output in team city81 override suspend fun specIgnored(kclass: KClass<*>, reason: String?) {}82 override suspend fun specFinished(kclass: KClass<*>, result: TestResult) {83 // if the spec itself has an error, we must insert a placeholder test84 when (val t = result.errorOrNull) {85 null -> Unit86 is MultipleExceptions -> t.causes.forEach { insertPlaceholder(it, kclass.toDescriptor()) }87 else -> insertPlaceholder(t, kclass.toDescriptor())88 }89 finishSpec(kclass)90 results.clear()91 children.clear()92 }93 private fun finishSpec(kclass: KClass<*>) {94 val msg = TeamCityMessageBuilder95 .testSuiteFinished(prefix, formatter.format(kclass))96 .id(kclass.toDescriptor().path().value)97 .locationHint(Locations.location(kclass))98 .build()99 println(msg)100 }101 override suspend fun testStarted(testCase: TestCase) {102 if (testCase.parent != null) addChild(testCase)103 when (testCase.type) {104 TestType.Container -> startTestSuite(testCase)105 TestType.Test -> startTest(testCase)106 TestType.Dynamic -> Unit107 }108 }109 override suspend fun testIgnored(testCase: TestCase, reason: String?) {110 ignoreTest(testCase, TestResult.Ignored(reason))111 }112 private fun addChild(testCase: TestCase) {113 children.getOrPut(testCase.descriptor.parent) { mutableListOf() }.add(testCase)114 }115 override suspend fun testFinished(testCase: TestCase, result: TestResult) {116 results[testCase.descriptor] = result117 when (testCase.type) {118 TestType.Container -> {119 failTestSuiteIfError(testCase, result)120 finishTestSuite(testCase, result)121 }122 TestType.Test -> {123 if (!started.contains(testCase.descriptor)) startTest(testCase)124 if (result.isErrorOrFailure) failTest(testCase, result)125 finishTest(testCase, result)126 }127 TestType.Dynamic -> {128 if (isParent(testCase)) {129 startTestSuite(testCase)130 failTestSuiteIfError(testCase, result)131 finishTestSuite(testCase, result)132 } else {133 startTest(testCase)134 if (result.isErrorOrFailure) failTest(testCase, result)135 finishTest(testCase, result)136 }137 }138 }139 }140 private fun failTestSuiteIfError(testCase: TestCase, result: TestResult) {141 // test suites cannot be in a failed state, so we must insert a placeholder to hold any error142 when (val t = result.errorOrNull) {143 null -> Unit144 is MultipleExceptions -> t.causes.forEach { insertPlaceholder(it, testCase.descriptor) }145 else -> insertPlaceholder(t, testCase.descriptor)146 }147 }148 // returns true if this test case is a parent149 private fun isParent(testCase: TestCase) = children.getOrElse(testCase.descriptor) { mutableListOf() }.isNotEmpty()150 /**151 * For a given [TestCase] will output the "test ignored" message.152 */153 private fun ignoreTest(testCase: TestCase, result: TestResult.Ignored) {154 val msg = TeamCityMessageBuilder155 .testIgnored(prefix, formatter.format(testCase))156 .id(testCase.descriptor.path().value)157 .parent(testCase.descriptor.parent.path().value)158 .locationHint(Locations.location(testCase.source))159 .message(result.reason)160 .result(result)161 .build()162 println(msg)163 }164 /**165 * For a [TestCase] will output the "test started" message.166 */167 private fun startTest(testCase: TestCase) {168 val msg = TeamCityMessageBuilder169 .testStarted(prefix, formatter.format(testCase))170 .id(testCase.descriptor.path().value)171 .parent(testCase.descriptor.parent.path().value)172 .locationHint(Locations.location(testCase.source))173 .build()174 println(msg)175 started.add(testCase.descriptor)176 }177 /**178 * For a given [TestCase] will output the "test failed" message.179 */180 private fun failTest(testCase: TestCase, result: TestResult) {181 val msg = TeamCityMessageBuilder182 .testFailed(prefix, formatter.format(testCase))183 .id(testCase.descriptor.path().value)184 .parent(testCase.descriptor.parent.path().value)185 .duration(result.duration)186 .locationHint(Locations.location(testCase.source))187 .withException(result.errorOrNull, details)188 .result(result)189 .build()190 println(msg)191 }192 /**193 * For a given [TestCase] will output the "test finished" message.194 */195 private fun finishTest(testCase: TestCase, result: TestResult) {196 val msg = TeamCityMessageBuilder197 .testFinished(prefix, formatter.format(testCase))198 .id(testCase.descriptor.path().value)199 .parent(testCase.descriptor.parent.path().value)200 .duration(result.duration)201 .locationHint(Locations.location(testCase.source))202 .result(result)203 .build()204 println(msg)205 }206 /**207 * For a given [TestCase] will output the "test suite started" message.208 */209 private fun startTestSuite(testCase: TestCase) {210 val msg = TeamCityMessageBuilder211 .testSuiteStarted(prefix, formatter.format(testCase))212 .id(testCase.descriptor.path().value)213 .parent(testCase.descriptor.parent.path().value)214 .locationHint(Locations.location(testCase.source))215 .build()216 println(msg)217 started.add(testCase.descriptor)218 }219 /**220 * For a given [TestCase] will output the "test suite finished" message.221 */222 private fun finishTestSuite(testCase: TestCase, result: TestResult) {223 val msg = TeamCityMessageBuilder224 .testSuiteFinished(prefix, formatter.format(testCase))225 .id(testCase.descriptor.path().value)226 .parent(testCase.descriptor.parent.path().value)227 .duration(result.duration)228 .locationHint(Locations.location(testCase.source))229 .result(result)230 .build()231 println(msg)232 }233}...
EnhancedConsoleTestEngineListener.kt
Source:EnhancedConsoleTestEngineListener.kt
...8import io.kotest.core.test.TestResult9import io.kotest.core.test.TestType10import io.kotest.engine.interceptors.EngineContext11import io.kotest.engine.test.names.DefaultDisplayNameFormatter12import io.kotest.engine.test.names.formatTestPath13import io.kotest.engine.test.names.getDisplayNameFormatter14import kotlin.reflect.KClass15import kotlin.time.Duration16/**17 * Generates test output to the console in an enhanced, formatted, coloured, way.18 * For a more basic output, see [BasicConsoleTestEngineListener]19 */20class EnhancedConsoleTestEngineListener(private val term: TermColors) : AbstractTestEngineListener() {21 private var errors = 022 private var start = System.currentTimeMillis()23 private var testsFailed = emptyList<Pair<TestCase, TestResult>>()24 private var testsIgnored = 025 private var testsPassed = 026 private var specsFailed = emptyList<Descriptor.SpecDescriptor>()27 private var specsSeen = emptyList<Descriptor>()28 private var slow = Duration.milliseconds(500)29 private var verySlow = Duration.milliseconds(5000)30 private var formatter:DisplayNameFormatter = DefaultDisplayNameFormatter(ProjectConfiguration())31 private fun green(str: String) = term.green(str)32 private fun greenBold(str: String) = term.green.plus(term.bold).invoke(str)33 private fun red(str: String) = term.red(str)34 private fun brightRed(str: String) = term.brightRed(str)35 private fun brightRedBold(str: String) = term.brightRed.plus(term.bold).invoke(str)36 private fun redBold(str: String) = term.red.plus(term.bold).invoke(str)37 private fun yellow(str: String) = term.yellow(str)38 private fun brightYellow(str: String) = term.brightYellow(str)39 private fun brightYellowBold(str: String) = term.brightYellow.plus(term.bold).invoke(str)40 private fun yellowBold(str: String) = term.yellow.plus(term.bold).invoke(str)41 private fun bold(str: String) = term.bold(str)42 private val intros = listOf(43 "Feeding the kotest engine with freshly harvested tests",44 "Engaging kotest engine at warp factor 9",45 "Harvesting the test fields",46 "Preparing to sacrifice your code to the demi-god of test",47 "Hamsters are turning the wheels of kotest",48 "Battle commanders are ready to declare war on bugs",49 "Be afraid - be very afraid - of failing tests",50 "The point is, ladies and gentlemen, that green is good",51 "Lock test-foils in attack position",52 "Fasten your seatbelts. It's going to be a bumpy test-run",53 "Lets crack open this test suite",54 "Lets get testing, I'm on the clock here",55 "Test time is the best time",56 "Open the test suite doors, HAL",57 "Mama always said testing was like a box of chocolates. You don't know which ones are gonna fail",58 "A test suite. Shaken, not stirred",59 "I'm going to make him a test he can't refuse",60 "You testing me? I don't see any other tests here, so you must be testing me",61 "I love the smell of tests in the morning",62 "Do you feel lucky punk? Do you think your tests will pass? Well, do ya?",63 "Mirab, with tests unfurled",64 "Dolly works 9 to 5. I test 24/7",65 "A test suite's gotta do what a test suite's gotta do",66 "I test code and chew bubblegum, and I'm all out of bubblegum"67 )68 override suspend fun engineInitialized(context: EngineContext) {69 formatter = getDisplayNameFormatter(context.configuration.registry, context.configuration)70 println(bold(">> Kotest"))71 println("- " + intros.shuffled().first())72 print("- Test plan has ")73 print(greenBold(context.suite.specs.size.toString()))74 println(" specs")75 println()76 }77 override suspend fun engineFinished(t: List<Throwable>) {78 if (specsSeen.isEmpty()) return79 if (t.isNotEmpty()) {80 errors += t.size81 t.forEach {82 printThrowable(it, 0)83 }84 }85 val duration = System.currentTimeMillis() - start86 val seconds = duration / 100087 if (errors == 0) {88 println(bold(">> All tests passed"))89 } else {90 println(redBold(">> There were test failures"))91 println()92 specsFailed.distinct().forEach { spec ->93 println(brightRedBold(" ${formatter.format(spec.kclass)}"))94 testsFailed.filter { it.first.spec::class.toDescriptor() == spec }.forEach { (testCase, _) ->95 println(brightRed(" - ${formatter.formatTestPath(testCase, " -- ")}"))96 }97 }98 }99 println()100 printSpecCounts()101 printTestsCounts()102 print("Time: ")103 println(bold("${seconds}s"))104 }105 private fun printThrowable(error: Throwable?, padding: Int) {106 if (error != null) {107 val message = error.message108 if (message != null) {109 println(brightRed(message.padStart(padding, ' ')))110 }111 error.stackTrace?.forEach {112 println(red("".padStart(padding + 2, ' ') + it))113 }114 }115 }116 private fun printSpecCounts() {117 val specsSeenSize = specsSeen.distinct().size118 val specsPassedSize = specsSeen.distinct().minus(specsFailed).size119 val specsFailedSize = specsFailed.distinct().size120 print("Specs: ")121 print(greenBold("$specsPassedSize passed"))122 print(", ")123 if (specsFailed.isEmpty()) {124 print(bold("$specsFailedSize failed"))125 print(bold(", "))126 } else {127 print(redBold("$specsFailedSize failed"))128 print(bold(", "))129 }130 println("$specsSeenSize total")131 }132 private fun printTestsCounts() {133 print("Tests: ")134 print(greenBold("$testsPassed passed"))135 print(", ")136 if (testsFailed.isEmpty()) {137 print(bold("${testsFailed.size} failed"))138 print(", ")139 } else {140 print(redBold("${testsFailed.size} failed"))141 print(", ")142 }143 if (testsIgnored > 0) {144 print(yellowBold("$testsIgnored ignored"))145 print(", ")146 } else {147 print(bold("$testsIgnored ignored"))148 print(", ")149 }150 println("${testsPassed + testsFailed.size + testsIgnored} total")151 }152 override suspend fun specStarted(kclass: KClass<*>) {153 specsSeen = specsSeen + kclass.toDescriptor()154 val specCount = specsSeen.size155 print(bold("$specCount. ".padEnd(4, ' ')))156 println(bold(formatter.format(kclass)))157 }158 override suspend fun specFinished(kclass: KClass<*>, result: TestResult) {159 if (result.isErrorOrFailure) {160 errors++161 specsFailed = specsFailed + kclass.toDescriptor()162 printThrowable(result.errorOrNull, 4)163 }164 println()165 }166 override suspend fun testIgnored(testCase: TestCase, reason: String?) {167 testsIgnored++168 print("".padEnd(testCase.descriptor.depth() * 4, ' '))169 print("- " + formatter.format(testCase))170 println(brightYellowBold(" IGNORED"))171 }172 private fun durationString(duration: Duration): String {173 return when {174 duration in slow..verySlow -> term.brightYellow("(${duration.inWholeMilliseconds}ms)")175 duration > verySlow -> term.brightRed("(${duration.inWholeMilliseconds}ms)")176 else -> ""177 }178 }179 override suspend fun testFinished(testCase: TestCase, result: TestResult) {180 // only leaf tests or failed containers contribute to the counts181 when (result) {182 is TestResult.Success -> if (testCase.type == TestType.Test) testsPassed++183 is TestResult.Failure, is TestResult.Error -> {184 errors++185 testsFailed = testsFailed + Pair(testCase, result)186 specsFailed = specsFailed + testCase.descriptor.spec()187 }188 else -> Unit189 }190 // we only print the name and status for leafs, as containers are printed in advance191 if (testCase.type == TestType.Test) {192 print("".padEnd(testCase.descriptor.depth() * 4, ' '))193 print("- " + formatter.format(testCase))194 when (result) {195 is TestResult.Success -> print(greenBold(" OK"))196 is TestResult.Error -> print(brightRed(" ERROR"))197 is TestResult.Failure -> print(brightRed(" FAILED"))198 is TestResult.Ignored -> print(brightYellow(" IGNORED"))199 }200 if (result.duration > slow) {201 print(" ${durationString(result.duration)}")202 }203 println()204 }205 if (result.errorOrNull != null) {206 println()207 printThrowable(result.errorOrNull, testCase.descriptor.depth() * 4)208 println()209 }210 }211 override suspend fun testStarted(testCase: TestCase) {212 // containers we display straight away without pass / fail message213 if (testCase.type == TestType.Container) {214 print("".padEnd(testCase.descriptor.depth() * 4, ' '))215 println("+ " + formatter.format(testCase))216 }217 }218}...
DefaultDisplayNameFormatter.kt
Source:DefaultDisplayNameFormatter.kt
...15fun getDisplayNameFormatter(registry: ExtensionRegistry, configuration: ProjectConfiguration): DisplayNameFormatter {16 return registry.all()17 .filterIsInstance<DisplayNameFormatterExtension>()18 .firstOrNull()19 ?.formatter() ?: DefaultDisplayNameFormatter(configuration)20}21/**22 * A default implementation of [DisplayNameFormatter].23 * Used when there are no registered [io.kotest.core.extensions.DisplayNameFormatterExtension]s.24 */25class DefaultDisplayNameFormatter(26 private val configuration: ProjectConfiguration,27) : DisplayNameFormatter {28 constructor() : this(ProjectConfiguration())29 override fun format(testCase: TestCase): String {30 val prefix = when (configuration.includeTestScopeAffixes ?: testCase.name.defaultAffixes) {31 true -> testCase.name.prefix ?: ""32 false -> ""33 }34 val suffix = when (configuration.includeTestScopeAffixes ?: testCase.name.defaultAffixes) {35 true -> testCase.name.suffix ?: ""36 false -> ""37 }38 val displayName = if (prefix.isBlank()) {39 when (configuration.testNameCase) {40 TestNameCase.Sentence -> testCase.name.testName.capital() + suffix41 TestNameCase.InitialLowercase -> testCase.name.testName.uncapitalize() + suffix42 TestNameCase.Lowercase -> testCase.name.testName.lowercase() + suffix43 else -> testCase.name.testName + suffix44 }45 } else {46 when (configuration.testNameCase) {47 TestNameCase.Sentence -> "${prefix.capital()}${testCase.name.testName.uncapitalize()}$suffix"48 TestNameCase.InitialLowercase -> "${prefix.uncapitalize()}${testCase.name.testName.uncapitalize()}$suffix"49 TestNameCase.Lowercase -> "${prefix.lowercase()}${testCase.name.testName.lowercase()}$suffix"50 else -> "$prefix${testCase.name.testName}$suffix"51 }52 }53 val name = if (configuration.testNameAppendTags) {54 return appendTagsInDisplayName(testCase, displayName)55 } else {56 displayName57 }58 return when (val parent = testCase.parent) {59 null -> name60 else -> if (configuration.displayFullTestPath) format(parent) + " " + name else name61 }62 }63 /**64 * Returns a formatted display name for this spec class.65 *66 * If the spec has been annotated with [DisplayName] (on supported platforms), then that will be used,67 * otherwise the default is to use the fully qualified class name.68 *69 * Note: This name must be globally unique. Two specs, even in different packages,70 * cannot share the same names, so if [DisplayName] is used, developers must ensure it does not71 * clash with another spec.72 */73 override fun format(kclass: KClass<*>): String {74 return when (platform) {75 Platform.JVM -> kclass.annotation<DisplayName>()?.wrapper ?: kclass.bestName()76 Platform.JS -> kclass.bestName()77 Platform.Native -> kclass.bestName()78 }79 }80}81fun appendTagsInDisplayName(testCase: TestCase, displayName: String): String {82 val tagNames = testCase.config.tags.joinToString(", ")83 return if (tagNames.isBlank()) {84 displayName85 } else {86 "${displayName}[tags = $tagNames]"87 }...
DisplayNameFormatter.kt
Source:DisplayNameFormatter.kt
1package io.kotest.core.names2import io.kotest.core.test.TestCase3import kotlin.reflect.KClass4/**5 * Returns formatted spec and test names for display or reporting purposes.6 */7interface DisplayNameFormatter {8 /**9 * Returns a formatted name for a test.10 */11 fun format(testCase: TestCase): String12 /**13 * Returns a formatted name for a spec class.14 */15 fun format(kclass: KClass<*>): String16}...
paths.kt
Source:paths.kt
1package io.kotest.engine.test.names2import io.kotest.core.names.DisplayNameFormatter3import io.kotest.core.test.TestCase4fun DisplayNameFormatter.formatTestPath(testCase: TestCase, separator: String): String {5 return when (val parent = testCase.parent) {6 null -> format(testCase)7 else -> format(parent) + separator + format(testCase)8 }9}...
format
Using AI Code Generation
1val displayNameFormatter = DisplayNameFormatter()2val formattedDisplayName = displayNameFormatter.format(displayName)3println(formattedDisplayName)4val testNameFormatter = TestNameFormatter()5val formattedTestName = testNameFormatter.format(testName)6println(formattedTestName)7val testPathFormatter = TestPathFormatter()8val formattedTestPath = testPathFormatter.format(testPath)9println(formattedTestPath)10val testPathFormatter = TestPathFormatter()11val formattedTestPath = testPathFormatter.format(testPath)12println(formattedTestPath)13val testNameFormatter = TestNameFormatter()14val formattedTestName = testNameFormatter.format(testName)15println(formattedTestName)16val displayNameFormatter = DisplayNameFormatter()17val formattedDisplayName = displayNameFormatter.format(displayName)18println(formattedDisplayName)19val testPathFormatter = TestPathFormatter()20val formattedTestPath = testPathFormatter.format(testPath)21println(formattedTestPath)22val testNameFormatter = TestNameFormatter()23val formattedTestName = testNameFormatter.format(testName)24println(formattedTestName)25val displayNameFormatter = DisplayNameFormatter()26val formattedDisplayName = displayNameFormatter.format(displayName)27println(formattedDisplayName)28val testPathFormatter = TestPathFormatter()29val formattedTestPath = testPathFormatter.format(testPath)30println(formattedTestPath)31val testPathFormatter = TestPathFormatter()32val formattedTestPath = testPathFormatter.format(testPath)33println(formattedTestPath)34val testNameFormatter = TestNameFormatter()35val formattedTestName = testNameFormatter.format(testName)36println(formattedTestName)
format
Using AI Code Generation
1 @DisplayName("format method should return string with proper format")2 fun `format method should return string with proper format`() {3 val displayNameFormatter = DisplayNameFormatter()4 val displayName = displayNameFormatter.format("my test")5 }6}
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!!