https://kotlinlang.org logo
Join Slack
Channels
announcements
100daysofcode
100daysofkotlin
100daysofkotlin-2021
advent-of-code
aem
ai
akkurate
alexa
algeria
algolialibraries
amper
amsterdam
android
android-architecture
android-databinding
androidgithubprojects
android-studio
androidthings
androidx
androidx-xprocessing
anime
anko
apollo-kotlin
appintro
appyx
arabic
argentina
arkenv
arksemdevteam
armenia
arrow
arrow-contributors
arrow-meta
ass
atlanta
atm17
atrium
austin
australia
austria
awesome-kotlin
aws-sdk
ballast
bangladesh
barcelona
bayarea
bazel
beepiz-libraries
belgium
benchmarks
berlin
big-data
books
boston
brazil
brikk
budapest
build
build-tools
bulgaria
bydgoszcz
cambodia
canada
carrat
carrat-dev
carrat-feed
chennai
chicago
chile
china
chucker
cincinnati-user-group
cli
clikt
cloudfoundry
cn
cobalt
code-coverage
codeforces
codemash-precompiler
codereview
codingame
codingconventions
coimbatore
collaborations
colombia
colorado
communities
competitivecoding
competitive-programming
compiler
compose
compose-android
compose-desktop
compose-destinations
compose-hiring
compose-ios
compose-mp
compose-ui-showcase
compose-wear
compose-web
confetti
connect-audit-events
corda
cork
coroutines
couchbase
coursera
croatia
cryptography
cscenter-course-2016
cucumber-bdd
cup-presentations
cyprus
czech
dagger
data2viz
databinding
datascience
dckotlin
debugging
decompose
decouple
denmark
dependency-injection
deprecated
detekt
detekt-hint
dev-core
dfw
docs-revamped
dokka
domain-driven-design
doodle
dsl
dublin
dutch
eap
eclipse
ecuador
edinburgh
education
effectivekotlin
effective-kotlin
emacs
embedded-kotlin
estatik
event21-community-content
events
exposed
failgood
fb-internal-demo
feed
firebase
fleet
flow
flowmvi
fluid-libraries
forkhandles
forum
fosdem
fp-in-kotlin
framework-elide
freenode
french
fritz2
fuchsia
fun-adaptive
functional
funktionale
gamedev
ge-kotlin
general-advice
georgia
geospatial
german-lang
getting-started
github-workflows-kt
glance
godot-kotlin
google-io
gradle
graphic
graphkool
graphql
graphql-kotlin
graviton-browser
greece
grpc
gsoc
gsoc-compose-multiplatform-storybook
gsoc-ij-gradle-plugin
gsoc-kmp-bazel
gsoc-kmp-bazel
gsoc-kmp-gemini-firebase
gsoc-kotlin-bom-bazel
gsoc-kotlin-lsp-project
gsoc-kotlin-openrewrite
gsoc-wasm-incremental-compilation
gui
hackathons
hamburg
hamkrest
helios
helsinki
hexagon
hibernate
hikari-cp
hire-me
hiring
hiring-french
hongkong
hoplite
http4k
hungary
hyderabad
image-processing
india
indonesia
inkremental
intellij
intellij-plugins
intellij-tricks
internships
introduce-yourself
io
ios
iran
israel
istanbulcoders
italian
j2k
jackson-kotlin
jadx
japanese
jasync-sql
javadevelopers
javafx
javalin
javascript
java-to-kotlin-refactoring
jdbi
jewel
jhipster-kotlin
jobsworldwide
jpa
jshdq
juul-libraries
jvm
jvm-ir-backend-feedback
jxadapter
k2-adopters
kaal
kafka
kakao
kalasim
kapt
karachi
karg
karlsruhe
kash_shell
kaskade
kbuild
kdbc
kgen-doc-tools
kgraphql
kilua
kinta
klaxon
klibs-io
klock
kloudformation
kmdc
kmm-español
kmongo
knbt
knote
koalaql
koans
kobalt
kobweb
kodein
kodex
kohesive
koin
koin-contributors
komapper
kondor-json
kong
konsist
konsist-dev
kontent
kontributors
koog-agentic-framework
korau
kore
korean
korge
korim
korio
korlibs
korte
kotest
kotest-contributors
kotless
kotlick
kotlinacademy
kotlin-asia
kotlin-beam
kotlinbot
kotlin-by-example
kotlinconf
kotlin-csv
kotlin-data-storage
kotlindl
kotlinforbeginners
kotlin-foundation
kotlin-fuel
kotlingforbeginners
kotlin-in-action
kotlin-inject
kotlin-kinetics
kotlin-latam
kotlin-logging
kotlinlondon
kotlinmad
kotlin-multiplatform-contest
kotlin-mumbai
kotlin-native
kotlin-pakistan
kotlin-plugin
kotlinprogrammers
kotlin-pune
kotlin-roadmap
kotlin-samples
kotlin-sap
kotlin-serbia
kotlin-spark
kotlinsu
kotlin-szeged
kotlintest
kotlintest-devs
kotlintlv
kotlinultimatechallenge
kotlin-website
kotlinx-collections-immutable
kotlinx-datetime
kotlinx-files
kotlinx-html
kotlinx-rpc
kotools
kotrix
kotson
kotzilla-platform
kovenant
kprompt
kraph
krawler
kroto-plus
ksp
kstatemachine
ktcc
ktfmt
ktlint
ktor
ktp
kubed
kug-leads
kug-torino
kvision
kweb
lambdaworld_cadiz
lanark
language-evolution
language-proposals
latvia
leakcanary
leedskotlinusergroup
lets-have-fun
libgdx
libkgd
library-development
lincheck
linenbot
linkeddata
lithuania
london
losangeles
lottie
love
lychee
macedonia
machinelearningbawas
madrid
malaysia
mathematics
meetkotlin
memes
meta
metro-detroit
mexico
miami
micronaut
minnesota
minutest
mirror
mockk
moko
moldova
monsterpuzzle
montreal
moonbean
morocco
motionlayout
mpapt
mu
multiplatform
mumbai
munich
mvikotlin
mvrx
myndocs-oauth2-server
naming
navigation-architecture-component
nepal
new-mexico
newname
new-zealand
nigeria
nodejs
norway
npm-publish
nyc
oceania
ohio-kotlin-users
oldenburg
olpaka
oolong
opensavvy
opensource
orbit-mvi
osgi
otpisani
package-search
pakistan
panamá
parameterize
pattern-matching
pbandk
pdx
peru
philippines
phoenix
pinoy
pocketgitclient
polish
popkorn
portugal
power-assert
practical-functional-programming
proguard
prozis-android-backup
pyhsikal
python
python-contributors
quasar
random
re
react
reaktive
realm
realworldkotlin
reductor
reduks
redux
redux-kotlin
refactoring-to-kotlin
reflect
refreshversions
reports
result
rethink
revolver
rhein-main
rocksdb
romania
room
rpi-pico
rsocket
russian
russian_feed
russian-kotlinasfirst
rx
rxjava
san-diego
science
scotland
scrcast
scrimage
script
scripting
seattle
serialization
server
sg-user-group
singapore
skia-wasm-interop-temp
skrape-it
slovak
snake
sofl-user-group
southafrica
spacemacs
spain
spanish
speaking
spek
spin
splitties
spotify-mobius
spring
spring-security
squarelibraries
stackoverflow
stacks
stayhungrystayfoolish
stdlib
stlouis
store
storyboard
storytale
strife-discord-lib
strikt
students
stuttgart
sudan
supabase-kt
swagger-gradle-codegen
swarm
sweden
swift-export
swing
swiss-user-group
switzerland
talking-kotlin
tallinn
tampa
teamcity
tegal
tempe
tensorflow
terminal
terpal
test
testing
testtestest
texas
tgbotapi
thailand
tornadofx
touchlab-tools
training
tricity-kotlin-user-group
trójmiasto
truth
tunisia
turkey
turkiye
twitter-feed
uae
udacityindia
uk
ukrainian
uniflow
unkonf
uruguay
utah
uuid
vancouver
vankotlin
vertx
videos
vienna
vietnam
vilnius-kug
vim
vkug
vuejs
webassembly
web-mpp
webrtc
wimix_sentry
wwdc
zircon
Powered by
# minutest
  • r

    robfletcher

    01/25/2021, 3:34 PM
    Copy code
    fun loginUser() = before {
      // do login things that may throw exceptions
    }
  • c

    christophsturm

    01/25/2021, 3:34 PM
    yeah. i think thats a reason to add before to failfast
  • c

    christophsturm

    01/25/2021, 3:36 PM
    right. but then loginUser() is not a normal api call thats tested and instead a test utility method
  • c

    christophsturm

    01/25/2021, 3:36 PM
    and you still need some kind of before support
  • r

    robfletcher

    01/25/2021, 3:36 PM
    right, and you have the problem of educating users to write things that way, which is not intuitive to people newer to Kotlin
  • d

    dmcg

    01/26/2021, 7:35 AM
    The problem comes down to wanting the computer to know which statements inside our context blocks should be lazy or not. We need eager for, for example, loops to define lots of tests, and lazy for things that should only happen when we actually execute.
  • d

    dmcg

    01/26/2021, 7:37 AM
    I went with a model of blocks to define the later, because it’s easy, at the expense of having to have a type for the fixture.
  • d

    dmcg

    01/26/2021, 7:39 AM
    I then made a virtue of the fixture type by claiming (I think rightly) that it aids test composition, and it certainly helps me think about where and when effects occur.
  • d

    dmcg

    01/26/2021, 7:40 AM
    Other models are available though - this is just the one that makes sense to me
  • d

    dmcg

    01/26/2021, 7:42 AM
    I vacillate between making all effects in the context, and having tests that just assert; and having context set up common state with tests that then modify it and then assert
  • d

    dmcg

    01/26/2021, 7:45 AM
    You can look at this as setting up all of the system in Given, no When, just Then; vs a common Given and then multiple When Thens
  • d

    dmcg

    01/26/2021, 7:47 AM
    It’s telling that Given When Then systems tend to have no nested contexts, and nested context systems tend to have no When Thens
  • c

    christophsturm

    01/26/2021, 11:24 AM
    when the fixture creation throws do you consider all the tests in the context and all of its subcontexts as failed?
  • c

    christophsturm

    01/26/2021, 11:32 AM
    in failfast i will report a failing context as a test failure (pretend the context is a single test)
  • c

    christophsturm

    01/26/2021, 11:33 AM
    actually when writing example code for subtests i thought that context and a test could be the same.
  • d

    dmcg

    01/26/2021, 11:34 AM
    From JUnit’s perspective, the fixture creation in the current and all parent contexts is part of the test itself.
  • c

    christophsturm

    01/26/2021, 11:35 AM
    ok so they automatically all fail.
  • d

    dmcg

    01/26/2021, 11:35 AM
    Yes, as there will be an invocation of all the code for each test
  • d

    dmcg

    01/26/2021, 3:13 PM
    I’ve just released v2.0.0-alpha to bintray! Please have play, and let me know if the upgrade path is smoothish:
    Copy code
    ## 2.0.0-alpha
    
    ### DSL changes (old methods deprecated)
    
    * before -> beforeEach
    * after -> afterEach
    * fixture -> given
    * modifyFixture -> beforeEach
    * deriveFixture -> given_
    
    ### DSL changes (old methods renamed)
    
    * test and test_ no longer take a TestDescriptor parameter to their block, but do supply the fixture as both receiver and parameter. The old versions are available as old_test and old_test_.
    
    ### Other DSL changes
    
    DSL functions with TestDescriptors are available in an Instrumented object.
    
    ### Test Engine
    
    The JUnit 5 (not Jupiter) test engine is now working well.
    It should find methods or top-level functions annotated @Testable, and you can even point to methods in IntelliJ and run them.
    Add this to Gradle to enable
    
    tasks.withType<Test> {
        useJUnitPlatform {
            includeEngines(
                "junit-jupiter", 
                "minutest" <-- This
            )
        }
    
    ### Parallel Test Running
    
    Run tests in each root context in parallel by setting a system property dev.minutest.parallel.
    Parallel running isn't on by default yet, but seems solid.
  • d

    dmcg

    01/26/2021, 3:18 PM
    I haven’t created a branch (trunk-based or die) so the docs GitHub don’t reflect the changes I’m afraid.
  • d

    dmcg

    01/26/2021, 9:00 PM
    But now I have, so you can see the new docs at https://github.com/dmcg/minutest/tree/v2
  • d

    dmcg

    03/31/2021, 6:04 PM
    I’ve published a 2.0 release candidate on Maven Central under dev.minutest
    👍 1
  • d

    dmcg

    03/31/2021, 6:05 PM
    It should be effectively backward compatible, but I hope to get around to publishing a last 1.x release to MC too
  • d

    dmcg

    03/31/2021, 6:10 PM
    As well as the 2.0 alpha changes, I propose to rename
    derivedContext
    to
    context_
    (with an underscore) to match the rename of
    deriveFixture
    to
    given_
  • d

    dmcg

    03/31/2021, 9:31 PM
    I’ve published v1.12 to Maven Central as v1.13
  • d

    dmcg

    09/20/2022, 10:58 AM
    I'm working my way towards another way of doing Minutest that might integrate better with tooling

    https://youtu.be/PnbV1rVI62I▾

  • d

    David Hamilton

    09/17/2023, 11:47 AM
    Any news on v2 of Minutest? 🙏
  • d

    dmcg

    09/18/2023, 10:00 PM
    Ah good question. It’s there in GitHub, but my day job doesn’t need it at the moment, and I was waiting for some feedback on the changes. You can try it out https://central.sonatype.com/artifact/dev.minutest/minutest?smo=true
    👍 1
    d
    • 2
    • 1
  • d

    dmcg

    09/18/2023, 10:00 PM
    theres 2.0.0-rc4
  • c

    christophsturm

    12/01/2023, 6:51 PM
    hey I am thinking about minutest style fixtures (or givens) and I have one problem that puzzles me: what do I do when one field of my fixture depends on a different field of my fixture and I don’t want to make my fixture nullable. heres a failgood test:
    Copy code
    val context = describe {
            val assertionError: AssertionError = AssertionError("failed")
            describe("with a typical valid root context") {
                val ctx =
                    RootContext("root context") {
                        test("failed test") { throw assertionError }
                    }
                describe("executing all the tests") {
                    val contextInfo = assertNotNull(execute(ctx) as? ContextInfo)
                    describe("reports failed tests") {
                        val failure =
                            contextInfo.tests.values
                                .awaitAll()
                                .map { it.result }
                                .filterIsInstance<Failure>()
                                .single()
                        it("reports exception for failed tests") {
                            expectThat(failure.failure) {
                                get { stackTraceToString() }
                                    .isEqualTo(assertionError.stackTraceToString())
                            }
                        }
                    }
    so the fixture is basically the rootcontext (ctx), and the assertionError (because in the test I need to have the assertion error to check that exactly that error is reported as failure) when I try to convert this to a given style (with my own made up test dsl) I have to make the context field nullable and mutable, because I need the given class constructed to reference the exception in my context.
    Copy code
    data class Given(
            val assertionError: java.lang.AssertionError,
            var context: RootContext? = null
        )
    
        val test =
            context(
                "contextExecutorTest port",
                given = {
                    val given = Given(AssertionError("failed"))
                    given.context =
                        RootContext("root context") {
                            test("failed test") {
                                throw given.assertionError
                            }
                        }
                    given
                }
            )
    is there a better way to do this and avoid making the context nullable?
    • 1
    • 1