kotest / kotest

Powerful, elegant and flexible test framework for Kotlin with assertions, property testing and data driven tests.
https://kotest.io
Apache License 2.0
4.42k stars 642 forks source link

Cant add Robolectric expermintal support to project #1122

Closed ukleiner closed 4 years ago

ukleiner commented 4 years ago

Ok, so we just added Robolectric experimental support. Please take a look at the snapshot builds and help us test it!

Originally posted by @Kerooker in https://github.com/kotlintest/kotlintest/issues/189#issuecomment-536223787 I'm trying to add Robolectric experimntal support. This is the simpel test

import io.kotest.experimental.robolectric.RobolectricExtension
import io.kotlintest.specs.DescribeSpec
import org.junit.jupiter.api.extension.ExtendWith
import strikt.api.expectThat
import strikt.assertions.isEqualTo

@ExtendWith(RobolectricExtension::class)
object ExampleUnitTest: DescribeSpec({
    describe("Example unit test") {
        describe("Addition") {
            it("can added") {
                expectThat(3)
                        .isEqualTo(1 + 2)
            }
        }
    }
})

but i get a Type mistmach error KClass<! out Extension> required. The same happens if I use ContainedRobolectricRunner instead.

I have in my build.gradle (app) the following line testImplementation 'io.kotest:kotest-extensions-robolectric:4.0.2798-SNAPSHOT' So that is not the issue. thanks for the help

LeoColman commented 4 years ago

Hey Wang! What's going on?

ukleiner commented 4 years ago

I'm new to all of this. I edited the original post with more information

LeoColman commented 4 years ago

I know this will be a little bit complicated right now, as we are experimenting a lot, but it should work:

First add the snapshot repository to your repositories:

repositories {
    maven(url = "https://oss.sonatype.org/content/repositories/snapshots/")
}

Then add the Robolectric Extension dependency to your dependencies:

dependencies {
    testImplementation("io.kotest:kotestextensions-robolectric:{snapshotVersion}")
}

Then in your tests that are going to use Robolectric, annotate them with @RobolectricTest.

To get robolectric working, you finally need to add it to your project config (if you don't know how to do that, take a look here)

override fun extensions() = listOf(RobolectricExtension())

So, an example test could go like this:

@RobolectricTest
class MyRobolectricTest : FunSpec() {

     init {
          test("My RobolectricTest") {
               1 + 1 shouldBe 2 // This will run inside Android Robolectric Environment
          }
     }
}

and your Project Configuration would be something like this:

package io.kotest.provided

class ProjectConfig : AbstractProjectConfig() {
    override fun extensions = listOf(RobolectricExtension())
}
ukleiner commented 4 years ago

thank you for your answer. I have problems arriving to the basic setup. I am using Spek as comparison since both frameworks have the same syntax and everything should work by only changing the class name. The example tests (I have two identical) look like this:

import io.kotlintest.specs.DescribeSpec
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.*

object TestTests: Spek({
    describe("testing"){
        it("tests") {
            assert(true)
        }
    }

})

With Spek my setup is:

  1. their plugin
  2. apply plugin: "de.mannodermaus.android-junit5" (in build.gradle of the module)
  3. testImplementation "org.junit.jupiter:junit-jupiter-api:5.5.2"
  4. testOptions { unitTests.all { useJUnitPlatform() } } Every test that has uses Spek works

When I use kotlintest I do:

  1. testImplementation 'io.kotlintest:kotlintest-runner-junit5:3.4.2'
    • builds fine
    • when running the tests (doesn't matter if im using kotlintest or not I get): SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder"
  2. I add testImplementation 'org.slf4j:slf4j-simple:1.7.25'
  3. tests (using Spek) run fine but in my console I get
    ~~~ Project Configuration ~~~
    -> Parallelism: 1 thread
    -> Test order: LexicographicSpecExecutionOrder
    -> Soft assertations: False
    -> Write spec failure file: False
    -> Fail on ignored tests: False
    -> Extensions
    - io.kotlintest.extensions.SystemPropertyTagExtension
    - io.kotlintest.extensions.RuntimeTagExtension
  4. Every test I run with DescribeSpec isn't found (Spek tests continue to work). If I run both tests with DescribeSpec I get "No tests were found".

When i wrote the original question neither problem (2, 4) happend. I "Invalidate Cache & Restart" I closed the project, deleted the .idea and *.iml files and imported I deleted the project and reopened it I tried kotlintest on another project

How do I get my tests detected? What am I missing? (after that I can tackle the robolectric part) thank you

LeoColman commented 4 years ago

It seems to me that Spek is stealing KotlinTest's execution.

I'm not sure if it's even possible to execute both tests in the same project. The same would happen if you tried to run TestNG tests together with JUnit tests.

@sksamuel Do you know if it's possible to use two JUnit runners in the same project without facing the issues @WangDea is describing?

Meanwhile, @WangDea Could you verify if you can run both tests with ./gradlew test?

Is your codebase using Spek or are you experimenting with both tools? I would suggest that, if possible, you use only one runner and stick to the one that works better for you.

ukleiner commented 4 years ago

I used Spek only as a baseline for comparison. I removed it from gradle.build & code, removed plugin, Invalidated and restarted project same problems occur. Running ./gradlew test I only get

BUILD SUCCESSFUL in 0s
28 actionable tasks: 28 up-to-date

I DON'T have a test block with useJUnitPlatform() since i get the following error Could not find method test() for arguments [build_65waqlvxxgxpqjuvrywpyrsti$_run_closure3@3b72328c] on project ':app' of type org.gradle.api.Project.

Instead I have testOptions { unitTests.all { useJUnitPlatform() } } (inside android {...})

ukleiner commented 4 years ago

Start a brand new kotlin project just to test it. My test looks like this

import io.kotlintest.specs.DescribeSpec

object testkotlinSpec: DescribeSpec({
    describe("test"){
        it("test"){
            assert(true)
        }
    }
})
sksamuel commented 4 years ago

@Kerooker can we still help @WangDea

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.