-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #185 from drcolombo/master
#178: added support for assertSoftly
- Loading branch information
Showing
130 changed files
with
1,015 additions
and
196 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
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
77 changes: 77 additions & 0 deletions
77
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,77 @@ | ||
package org.amshove.kluent | ||
|
||
expect val errorCollector: ErrorCollector | ||
|
||
enum class ErrorCollectionMode { | ||
Soft, Hard | ||
} | ||
|
||
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() | ||
} | ||
|
||
open class BasicErrorCollector : ErrorCollector { | ||
|
||
private val failures = mutableListOf<Throwable>() | ||
private var mode = ErrorCollectionMode.Hard | ||
|
||
override fun getCollectionMode(): ErrorCollectionMode = mode | ||
|
||
override fun setCollectionMode(mode: ErrorCollectionMode) { | ||
this.mode = mode | ||
} | ||
|
||
override fun pushError(t: Throwable) { | ||
failures.add(t) | ||
} | ||
|
||
override fun errors(): List<Throwable> = failures.toList() | ||
|
||
override fun clear() = failures.clear() | ||
} | ||
|
||
/** | ||
* 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
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
Oops, something went wrong.