atrium v0.9.0-alpha2 Release Notes
Release Date: 2020-01-11 // over 4 years ago-
This is a pre-release for early adopters using currently
cc.en_GB
and want to switch tofluent.en_GB
which makes use ofExpect
instead ofAssert
Following the setup instructions:
dependencies { testImplementation "ch.tutteli.atrium:atrium-fluent-en_GB:0.9.0-alpha2" }
๐ Proper release notes will follow with the final release of
0.9.0
.
Already many thanks to all the contributorsFollowing already the migration guide.
๐ Migrating deprecated functionality
๐ In case you migrate from a version < 0.7.0 then please have a look at the migration guide given in the Release Notes of 0.7.0.
Otherwise you can use the suggested replacements (ALT + Enter -> Replace with ...) or the search/replace patterns shown below.Notice, that you don't have to migrate everything at once where
asExpect
andasAssert
allow to switch between the oldAssert
and the newExpect
world.
Ping us in the Atrium slack channel if you need help.The following command is carrying out the points 1 to 10 described below (don't forget the points 11, 12, ...), run it from the root of your project, no guarantees that your system is capable of carrying it out. If not, you can use the manual steps described below.
find ./ -name "*.kt" | xargs perl -0777 -i \ -pe 's/AssertImpl([\n\r\s]*)\.changeSubject\(([^\)\n]+)\)[\n\r\s]*\{[\n\r\s]*subject/ExpectImpl$1.changeSubject\($2\)$1.unreported \{ it/g;' \ -pe 's/AssertImpl([\n\r\s]*)\.changeSubject\(([^\)]+)\)/ExpectImpl$1.changeSubject\($2\).unreported/g;' \ -pe 's/AssertImpl([\n\r\s]*)\.builder([\n\r\s]*)\.createDescriptive\(([^,\n]+,[^\)]+\)[\n\r\s]*\{[\n\r\s]*)plant.subject/AssertImpl([\n\r\s]*)\.builder([\n\r\s]*)\.createDescriptive\(([^,\n]+,[^\)]+\)[\n\r\s]*\{[\n\r\s]*)plant.subject/g;' \ -pe 's/AssertImpl([\n\r\s]*)\.builder([\n\r\s]*)\.descriptive([\n\r\s]*).withTest(\(?[\n\r\s]*)\{([\n\r\s]*)plant.subject/AssertImpl$1.builder$2.descriptive$3.withTest\(plant\)$4\{$5it/g;' \ -pe 's/AssertImpl([\n\r\s]*)\.builder([\n\r\s]*)\.descriptive([\n\r\s]*).withTest(\(?[\n\r\s]*)\{([\n\r\s]*)subject/AssertImpl$1.builder$2.descriptive$3.withTest\(this\)$4\{$5it/g;' \ -pe 's/(?:property|returnValueOf|rueckgabewertVon)\((?:[\n\r\s]*)subject::([^\)]+)\)(\s*\{)/feature(\{ f(it::$1) \})$2/g;' \ -pe 's/(?:property|returnValueOf|rueckgabewertVon)\((?:[\n\r\s]*)subject::([^\)]+)\)/feature \{ f(it::$1) \}/g;' \ -pe 's/(?:property|returnValueOf|rueckgabewertVon)\((?:[\n\r\s]*)subject::([^\)]+)\)(\s*\{)`/feature(\{ f(it::$1) \})$2/g;' \ -pe 's/(?:property|returnValueOf|rueckgabewertVon)\(([A-Z][^:]+)::([^\)]+)\)/feature($1::$2)/g;' \ -pe 's/(?:property|returnValueOf|rueckgabewertVon)\(([^:]+)::([^\)]+)\)/feature("$1.$2", { $1.$2 })/g;' \ -pe 's/(import ch\.tutteli\.atrium\.api\.cc\.(?:\.infix)?(?:en_GB|de_CH))\.(property|returnValueOf)/$1.feature/g;' \ -pe 's/(\.| )((?:toThrow|wirft|isA|istEin)<.*>)\s*\{\s*\}/$1$2()/g;' \ -pe 's/notToBeNull\s*\{\s*\}/notToBe(null)/g;' \ -pe 's/fun <T\s*:\s*Any> ([^\(]+)\(subject:\s*T\)[\n\r\s]*=[\n\r\s]*AssertImpl[\n\r\s]*\.coreFactory[\n\r\s]*\.newReportingPlant\(([^,]+),[\n\r\s]*\{\s*subject\s*\}[\n\r\s]*,[\n\r\s]*reporter\)/fun <T> $1\(subject: T\): Expect<T> = \n ExpectBuilder.forSubject\(subject\)\n .withVerb\($2\)\n .withoutOptions\(\)\n .build\(\)/g;' \ -pe 's/fun <T\s*:\s*Any> ([^\(]+)\(subject:\s*T\s*,[\n\r\s]*assertionCreator: Assert<T>.\(\)\s*->\s*Unit\)[\n\r\s]*=[\n\r\s]*AssertImpl[\n\r\s]*\.coreFactory[\n\r\s]*\.newReportingPlantAndAddAssertionsCreatedBy\(([^,]+),[\n\r\s]*\{\s*subject\s*\}[\n\r\s]*,[\n\r\s]*reporter,[\n\r\s]*assertionCreator\)/fun <T> $1\(subject: T, assertionCreator: Expect<T>.\(\) -> Unit\): Expect<T> = \n $1(subject).addAssertionsCreatedBy(assertionCreator)/g;' \ -pe 's/(?:internal )?fun <T(?:\s*:\s*Any\?)?> ([^\(]+)\(subject:\s*T\)[\n\r\s]*=[\n\r\s]*AssertImpl[\n\r\s]*\.coreFactory[\n\r\s]*\.newReportingPlantNullable\(([^,]+),[\n\r\s]*\{\s*subject\s*\}[\n\r\s]*,[^\)]+\)//g;' \ -pe 's/import ch.tutteli.atrium.verbs\.(expect|assert|assertThat)/import ch.tutteli.atrium.api.verbs.$1/g;' \ -pe 's/AssertImpl/ExpectImpl/g;' \ -pe 's/fun Assert(?:ionPlant(?:Nullable)?)?<(.*)>\./fun <T: $1> Expect<T>\./g;' \ -pe 's/Assert(ionPlant(Nullable)?)?</Expect</g;' \ -pe 's/import ch\.tutteli\.atrium\.creating\.Assert(ionPlant(Nullable)?)?/import ch.tutteli.atrium.creating.Expect/g;' \ -pe 's/import ch.tutteli\.atrium\.api\.cc\.(en_GB|de_CH)/import ch.tutteli.atrium.api.fluent.$1/g;' \ -pe 's/import ch.tutteli\.atrium\.api\.cc\.infix\.en_GB/import ch.tutteli.atrium.api.infix.en_GB/g;'
The following list helps you to migrate faster by using a few regex search replace commands (in Intellij). Make sure you have checked
Regex
as well asMatch Case
in the search options. Notice, that the good will certainly not compile after a single replace, you need to carry out all search&replace commands.
It is not perfect, maybe you need to do a few adjustments in addition, let us now and we improve the search/replace commands here.Switch to ExpectImpl.changeSubject instead of using AssertImpl.changeSubject:
Search:AssertImpl([\n\r\s]*)\.changeSubject\(([^\)\n]+)\)[\n\r\s]*\{[\n\r\s]*subject
Replace:ExpectImpl$1.changeSubject\($2\)$1.unreported { it
Search:
AssertImpl([\n\r\s]*)\.changeSubject\(([^\)]+)\)
Replace:ExpectImpl$1.changeSubject\($2\).unreported
๐ builder.descriptive, safe withTest
๐ Search:
AssertImpl([\n\r\s]*)\.builder([\n\r\s]*)\.createDescriptive\(([^,\n]+,[^\)]+\)[\n\r\s]*\{[\n\r\s]*)plant.subject
๐ Replace:AssertImpl$1.builder$2.createDescriptive\(plant, $3it
๐ Search:
AssertImpl([\n\r\s]*)\.builder([\n\r\s]*)\.descriptive([\n\r\s]*).withTest(\(?[\n\r\s]*)\{([\n\r\s]*)plant.subject
๐ Replace:AssertImpl$1.builder$2.descriptive$3.withTest\(plant\)$4{$5it
๐ Search:
AssertImpl([\n\r\s]*)\.builder([\n\r\s]*)\.descriptive([\n\r\s]*).withTest(\(?[\n\r\s]*)\{([\n\r\s]*)subject
๐ Replace:AssertImpl$1.builder$2.descriptive$3.withTest\(this\)$4{$5it
๐ use new feature mechanism
This one needs extra care as arguments could be function calls. Verify the replacements
Search:
(?:property|returnValueOf|rueckgabewertVon)\((?:[\n\r\s]*)subject::([^\)]+)\)(\s*\{)
Replace:feature(\{ f(it::$1) \})$2
Search:
(?:property|returnValueOf|rueckgabewertVon)\((?:[\n\r\s]*)subject::([^\)]+)\)
Replace:feature \{ f(it::$1) \}
Search:
(?:property|returnValueOf|rueckgabewertVon)\(([A-Z][^:]+)::([^\)]+)\)
Replace:feature($1::$2)
Search:
(?:property|returnValueOf|rueckgabewertVon)\(([^:]+)::([^\)]+)\)
Replace:feature("$1.$2", { $1.$2 })
Search:
(import ch\.tutteli\.atrium\.api\.cc\.(?:\.infix)?(?:en_GB|de_CH))\.(property|returnValueOf)
Replace:$1.feature
toThrow and isA with empty assertionCreator lambda
Search:(\.| )((?:toThrow|wirft|isA|istEin)<.*>)\s*\{\s*\}
Replace$1$2()
notToBeNull with empty assertionCreator lambda
Search:notToBeNull\s*\{\s*\}
Replace:notToBe(null)
migrate custom assertion verbs:
Search:
fun <T\s*:\s*Any> ([^\(]+)\(subject:\s*T\)[\n\r\s]*=[\n\r\s]*AssertImpl[\n\r\s]*\.coreFactory[\n\r\s]*\.newReportingPlant\(([^,]+),[\n\r\s]*\{\s*subject\s*\}[\n\r\s]*,[\n\r\s]*reporter\)
Replace:
๐fun <T> $1\(subject: T\): Expect<T> = \n ExpectBuilder.forSubject\(subject\)\n .withVerb\($2\)\n .withoutOptions\(\)\n .build\(\)
Search:
fun <T\s*:\s*Any> ([^\(]+)\(subject:\s*T\s*,[\n\r\s]*assertionCreator: Assert<T>.\(\)\s*->\s*Unit\)[\n\r\s]*=[\n\r\s]*AssertImpl[\n\r\s]*\.coreFactory[\n\r\s]*\.newReportingPlantAndAddAssertionsCreatedBy\(([^,]+),[\n\r\s]*\{\s*subject\s*\}[\n\r\s]*,[\n\r\s]*reporter,[\n\r\s]*assertionCreator\)
Replace:
fun <T> $1\(subject: T, assertionCreator: Expect<T>.\(\) -> Unit\): Expect<T> = \n $1(subject).addAssertionsCreatedBy(assertionCreator)
Search:
(?:internal )?fun <T(?:\s*:\s*Any\?)?> ([^\(]+)\(subject:\s*T\)[\n\r\s]*=[\n\r\s]*AssertImpl[\n\r\s]*\.coreFactory[\n\r\s]*\.newReportingPlantNullable\(([^,]+),[\n\r\s]*\{\s*subject\s*\}[\n\r\s]*,[^\)]+\)
Replace:(empty string)
In case the above search&replace did not find anything (because your code is different):
๐จ Switch fromAssertImpl.coreFactory.newReportingPlant
toExpectBuilder
๐ => see atriumVerbs.kt for an example of how own assertion verbs are defined now; or use the suggested replacements but please addimport ch.tutteli.atrium.domain.builders.reporting.ExpectBuilder
first as it will not work correctly otherwise due to an Intellij bug
=> Note that you don't need a verb for nullable types any more. Thus:- remove the upper bound
T: Any
- remove the verb which uses `newReportingPlantNullable
- remove the verb which expected
act: () -> Unit
Switch to new built-in assertion verbs which use Expect
Search: import ch.tutteli.atrium.verbs.(expect|assert|assertThat)
Replace: import ch.tutteli.atrium.api.verbs.$1Switch from AssertImpl to ExpectImpl
Search:
AssertImpl
Replace:ExpectImpl
Switch all your assertion functions to use Expect and no longer Assert:
Search:
import ch\.tutteli\.atrium\.creating\.Assert(ionPlant(Nullable)?)?
Replace:import ch.tutteli.atrium.creating.Expect
Search:
fun Assert(?:ionPlant(?:Nullable)?)?<(.*)>\.
Replace:fun <T: $1> Expect<T>\.
Search:
Assert(ionPlant(Nullable)?)?<
Replace:Expect<
Switch the API
Search:
import ch.tutteli\.atrium\.api\.cc\.(en_GB|de_CH)
Replace:import ch.tutteli.atrium.api.fluent.$1
Search:
import ch.tutteli\.atrium\.api\.cc\.infix\.en_GB
Replace:import ch.tutteli.atrium.api.infix.en_GB
In case you have custom assertion verbs
Dealing with thrown exceptions is now handled by Expect as well.
๐ป However, in case you have named the assertion verb differently for expecting an Exception then you have to decide:- ๐ use the same name => rename the corresponding function which expects
act: () -> Unit
to the same name and remove it afterwards - ๐ use a different name => delegate the function which expects
act: () -> Unit
to the other verb
๐ Check if you need to add
import ch.tutteli.atrium.domain.builders.reporting.ExpectBuilder
Try to reduce duplicate Expect imports
Repeat until you don't have duplicate imports anymore
Search:import ch\.tutteli\.atrium\.creating\.Expect\n\s*import ch\.tutteli\.atrium\.creating\.Expect
Replace:import ch.tutteli.atrium.creating.Expect
โ Try to compile your project and watch out for the following warnings:
'MyClass' is a final type, and thus a value of the type parameter is predetermined
=> you can suppress this warning by adding@file:Suppress("FINAL_UPPER_BOUND")
to your file, this is actually a Kotlin bug (https://youtrack.jetbrains.com/issue/KT-34257)
- remove the upper bound