forked from MarkusAmshove/Kluent
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MarkusAmshove#178: added support for assertSoftly
- Loading branch information
Showing
96 changed files
with
577 additions
and
114 deletions.
There are no files selected for viewing
47 changes: 47 additions & 0 deletions
47
common/src/main/kotlin/org/amshove/kluent/AssertionErrors.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package org.amshove.kluent | ||
|
||
import kotlin.test.assertFails | ||
|
||
/** An error that bundles multiple other [Throwable]s together */ | ||
class MultiAssertionError(errors: List<Throwable>) : AssertionError(createMessage(errors)) { | ||
companion object { | ||
private fun createMessage(errors: List<Throwable>) = buildString { | ||
append("\nThe following ") | ||
|
||
if (errors.size == 1) { | ||
append("assertion") | ||
} else { | ||
append(errors.size).append(" assertions") | ||
} | ||
append(" failed:\n") | ||
|
||
if (errors.size == 1) { | ||
append(errors[0].message).append("\n") | ||
stacktraces.throwableLocation(errors[0])?.let { | ||
append("\tat ").append(it).append("\n") | ||
} | ||
} else { | ||
for ((i, err) in errors.withIndex()) { | ||
append(i + 1).append(") ").append(err.message).append("\n") | ||
stacktraces.throwableLocation(err)?.let { | ||
append("\tat ").append(it).append("\n") | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
fun assertionError(error: Throwable): Throwable { | ||
val message = buildString { | ||
append("\nThe following assertion failed:\n") | ||
|
||
append(error.message).append("\n") | ||
stacktraces.throwableLocation(error)?.let { | ||
append("\tat ").append(it).append("\n") | ||
} | ||
} | ||
val t = AssertionError(message) | ||
stacktraces.cleanStackTrace(t) | ||
return t | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
common/src/main/kotlin/org/amshove/kluent/ErrorCollector.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package org.amshove.kluent | ||
|
||
expect val errorCollector: ErrorCollector | ||
|
||
enum class ErrorCollectionMode { | ||
Soft, Hard | ||
} | ||
|
||
typealias Clue = () -> String | ||
|
||
interface ErrorCollector { | ||
|
||
fun getCollectionMode(): ErrorCollectionMode | ||
|
||
fun setCollectionMode(mode: ErrorCollectionMode) | ||
|
||
/** | ||
* Returns the errors accumulated in the current context. | ||
*/ | ||
fun errors(): List<Throwable> | ||
|
||
/** | ||
* Adds the given error to the current context. | ||
*/ | ||
fun pushError(t: Throwable) | ||
|
||
/** | ||
* Clears all errors from the current context. | ||
*/ | ||
fun clear() | ||
|
||
fun pushClue(clue: Clue) | ||
|
||
fun popClue() | ||
|
||
/** | ||
* Returns the current clue context. | ||
* That is all the clues nested to this point. | ||
*/ | ||
fun clueContext(): List<Clue> | ||
} | ||
|
||
open class BasicErrorCollector : ErrorCollector { | ||
|
||
private val failures = mutableListOf<Throwable>() | ||
private var mode = ErrorCollectionMode.Hard | ||
private val clues = mutableListOf<Clue>() | ||
|
||
override fun getCollectionMode(): ErrorCollectionMode = mode | ||
|
||
override fun setCollectionMode(mode: ErrorCollectionMode) { | ||
this.mode = mode | ||
} | ||
|
||
override fun pushClue(clue: Clue) { | ||
clues.add(0, clue) | ||
} | ||
|
||
override fun popClue() { | ||
clues.removeAt(0) | ||
} | ||
|
||
override fun clueContext(): List<Clue> = clues.toList() | ||
|
||
override fun pushError(t: Throwable) { | ||
failures.add(t) | ||
} | ||
|
||
override fun errors(): List<Throwable> = failures.toList() | ||
|
||
override fun clear() = failures.clear() | ||
} | ||
|
||
fun clueContextAsString() = errorCollector.clueContext().let { | ||
if (it.isEmpty()) "" else it.joinToString("\n", postfix = "\n") { f -> f.invoke() } | ||
} | ||
|
||
/** | ||
* If we are in "soft assertion mode" will add this throwable to the | ||
* list of throwables for the current execution. Otherwise will | ||
* throw immediately. | ||
*/ | ||
fun ErrorCollector.collectOrThrow(error: Throwable) { | ||
when (getCollectionMode()) { | ||
ErrorCollectionMode.Soft -> pushError(error) | ||
ErrorCollectionMode.Hard -> throw error | ||
} | ||
} | ||
|
||
/** | ||
* The errors for the current execution are thrown as a single | ||
* throwable. | ||
*/ | ||
fun ErrorCollector.throwCollectedErrors() { | ||
// set the collection mode back to the default | ||
setCollectionMode(ErrorCollectionMode.Hard) | ||
val failures = errors() | ||
clear() | ||
if (failures.isNotEmpty()) { | ||
val t = MultiAssertionError(failures) | ||
stacktraces.cleanStackTrace(t) | ||
throw t | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package org.amshove.kluent | ||
|
||
inline fun <T> assertSoftly(assertions: () -> T): T { | ||
// Handle the edge case of nested calls to this function by only calling throwCollectedErrors in the | ||
// outermost verifyAll block | ||
if (errorCollector.getCollectionMode() == ErrorCollectionMode.Soft) { | ||
return assertions() | ||
} | ||
errorCollector.setCollectionMode(ErrorCollectionMode.Soft) | ||
return assertions().apply { | ||
errorCollector.throwCollectedErrors() | ||
} | ||
} | ||
|
||
inline fun <T> assertSoftly(t: T, assertions: T.(T) -> Unit): T { | ||
return assertSoftly { | ||
t.assertions(t) | ||
t | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package org.amshove.kluent | ||
|
||
expect val stacktraces: StackTraces | ||
|
||
object BasicStackTraces : StackTraces { | ||
override fun throwableLocation(t: Throwable): String? = null | ||
override fun throwableLocation(t: Throwable, n: Int): List<String>? = null | ||
override fun <T : Throwable> cleanStackTrace(throwable: T): T = throwable | ||
override fun root(throwable: Throwable): Throwable = throwable | ||
} | ||
|
||
interface StackTraces { | ||
|
||
/** | ||
* Returns the first line of this stack trace, skipping io.kotest if possible. | ||
* On some platforms the stack trace may not be available and will return null. | ||
*/ | ||
fun throwableLocation(t: Throwable): String? | ||
|
||
/** | ||
* Returns the first n lines of this stack trace, skipping io.test if possible. | ||
* On some platforms the stack trace may not be available and will return null. | ||
*/ | ||
fun throwableLocation(t: Throwable, n: Int): List<String>? | ||
|
||
/** | ||
* Removes io.kotest stack elements from the given throwable if the platform supports stack traces, | ||
* otherwise returns the exception as is. | ||
*/ | ||
fun <T : Throwable> cleanStackTrace(throwable: T): T | ||
|
||
/** | ||
* Returns the root cause of the given throwable. If it has no root cause, or the platform does | ||
* not support causes, this will be returned. | ||
*/ | ||
fun root(throwable: Throwable): Throwable | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
.../kotlin/org/amshove/kluent/DataClasses.kt → ...n/org/amshove/kluent/tests/DataClasses.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package org.amshove.kluent | ||
package org.amshove.kluent.tests | ||
|
||
data class Person(val name: String, val surname: String) | ||
|
2 changes: 1 addition & 1 deletion
2
...shove/kluent/basic/ShouldBeDigitShould.kt → ...kluent/tests/basic/ShouldBeDigitShould.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...mshove/kluent/basic/ShouldBeNullShould.kt → .../kluent/tests/basic/ShouldBeNullShould.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...rg/amshove/kluent/basic/ShouldBeShould.kt → ...hove/kluent/tests/basic/ShouldBeShould.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...amshove/kluent/basic/ShouldEqualShould.kt → ...e/kluent/tests/basic/ShouldEqualShould.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.