-
Notifications
You must be signed in to change notification settings - Fork 53
Jetpack compose support #234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thank you for bringing this up! Unfortunately, test rules are a concept exclusive to JUnit 4 and a new implementation is required to make them work with JUnit 5 (similar to the I might consider ramping up a library for Compose support in the near future, once that API stabilizes a little further. Until then, please continue to write your Compose UI tests against the JUnit 4 APIs. If you don't mind, I'd like to keep this ticket around to keep visibility and gauge interest from people towards this feature. 🙏 |
Any update on this? Compose is getting its stable release now (currently |
Nothing substantial. I did have a look through the test source code of Jetpack Compose a few months ago, unfortunately leaving quite disappointed: There is a lot of tight coupling to JUnit 4 so we'd need to copy-paste and rewrite the entire thing, pretty much. I would've liked some sort of abstraction similar to what recent efforts in |
I was celebrating the stable release of Jetpack Compose by giving the integration another shot. It's a very, very simple example but I managed to create a bridge to Compose via the existing JUnit 4 stuff. Feels great to see a There's still a lot to come and I need many more hours to refine this hacky approach, but I'm quite happy about this. 🎉🎉 |
Seems promising! |
Looks great! Would you mind sharing the extension's code as a workaround until this feature is released? |
I've spent a bit of time drafting the initial PR for this and pulled in what I had been experimenting with before. You can get it from Sonatype's snapshot repository: dependencies {
androidTestImplementation("de.mannodermaus.junit5:android-test-compose:0.1.0-SNAPSHOT")
} Usage: class YourTest {
@RegisterExtension
@JvmField
val extension = createComposeExtension()
@Test
fun test() {
extension.setContent {
// Your composable
}
}
} I'll be tracking progress over time over at #257 |
I created a simple workaround for this. All you need is:
Now you can use the Extension:
For me it works for now. And there are no dangerous pitfalls with threads here |
Thanks for your input @VitaliyDoskoch! I like how your solution works without any multithreading, it's very concise in that way. One of the things that is lacking with the I've taken it as inspiration to draft a new version of the
// Usage 1
@ExtendWith(AndroidComposeExtension::class)
class ClassComposeExtensionTests {
@Test
fun test(extension: ComposeExtension) = extension.runComposeTest {
setContent {
Column {
Text(text = "Hello World")
}
}
onNodeWithText("Hello World").assertIsDisplayed()
}
}
// Usage 2
class FieldComposeExtensionTests {
@JvmField
@RegisterExtension
val extension = createAndroidComposeExtension<MyCustomActivity>()
@Test
fun test() = extension.runComposeTest {
setContent {
Column {
Text(text = "Hello World")
}
}
onNodeWithText("Hello World").assertIsDisplayed()
}
} I'm very glad that I could delete the thread shenanigans again. Expect a new snapshot of 0.1.0 for the compose artifact within the next couple of hours. |
I've run into an issue with 1.0.0-SNAPSHOT version. The problem is that I cannot use code examples: using junit4
trying to achieve the same with junit5
I've tried to workaround it with:
Is there any way out of this situation (apart from writing monolithic tests without |
Also I've noticed another, minor issue - junit4:
junit5 has to cast
|
Thanks for your feedback, @Piotr-Smietana-Intent! I'm also not quite happy with the extension API for JUnit 5 yet, and your |
Any plans to make this support stable? 🙂 |
Compose supports more than just Android, too, and those of us writing tests for desktop apps also want a The cross-platform equivalent of I was attempting to write an extension to replace the test rule for desktop tests, and more or less hit the same problems described here. A lot of the code their test rule is using is internal, so I would end up copying those things into my code as well, and eventually I would have all the code in their module duplicated in mine. :( I opened a ticket at compose-jb asking for them to consider using JUnit 5 instead of 4. The test API is still experimental, so wild changes in how it works are already expected. |
I tested this out - this is working great; very cool!
I ran into an issue with this:
I get an error: Cannot inline bytecode built with JVM target 11 into bytecode that is being built with JVM target 1.8. Please specify proper '-jvm-target' option I may have missed something in setup? Here's a link to my test (along w/the full project): https://github.com/santansarah/sharedtest-junit5-turbine/blob/compose-testing/app/src/androidTest/java/com/santansarah/sharedtestjunit5turbine/compose/ComposeTestActivity.kt
|
@santansarah
If it still does not work, check your preferences and ensure that the Kotlin compiler uses the same JVM target. I then had to "Invalidate Caches..." and after a restart of Android Studio, everything worked fine. |
Hi @Faltenreich - I changed my compile options to version 11; I also updated my project plugins + dependencies. Everything is working great - thanks so much! |
Was |
No, shouldn't be. 🤔 The Maven Central snapshots repository lists the data for it just like before. Please make sure that the repo is available to your module and that Gradle offline mode isn't on by accident (speaking from experience there). |
Hello everybody! I wanted to share an update for the Compose integration, as I finally had a bit of time to spend on this endeavor over the last couple of nights. Please update your dependency declarations as follows: dependencies {
androidTestImplementation("de.mannodermaus.junit5:android-test-compose:1.0.0-SNAPSHOT")
androidTestImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3")
debugImplementation("androidx.compose.ui:ui-test-manifest:1.4.3")
} Also, make sure to use the latest Gradle plugin for JUnit 5 ( class MyTests {
@JvmField
@RegisterExtension
@ExperimentalTestApi
val extension = createComposeExtension()
// or, if you want to test your own Activity:
// val extension = createAndroidComposeExtension<MyActivity>()
@BeforeEach
fun beforeEach() {
extension.use {
// You can do set-up logic here...
}
}
@Test
fun test() {
extension.use {
// ...and run the actual test here!
setContent {
Button(onClick = {}) {
Text("button")
}
}
onNodeWithText("button").performClick()
}
}
}
There may very well be a bunch of cases that aren't working 100% yet, so please keep letting me know about those. 🥳 |
This is working great so far, thanks! I was wondering if its possible to have the Activity start with a particular intent? For reference, I found this post - where with the junit4 approach there seems to be ways to do this: https://stackoverflow.com/questions/68267861/add-intent-extras-in-compose-ui-test I'm having trouble figuring out if the equivalent is possible here. It looks like if we could provide this function:
with a custom
https://developer.android.com/reference/androidx/test/core/app/ActivityScenario#launch(android.content.Intent) Update: Added this PR, let me know if this makes sense or not: #301 |
The inaugural version of Compose, including the additions by @compscidr, have been released! To keep in line with the versioning of the other instrumentation libraries, I bumped the Compose artifact to dependencies {
androidTestImplementation("de.mannodermaus.junit5:android-test-compose:1.4.0")
} |
Thanks, this is great! Should I expect it to work for Compose Desktop? |
I am getting a warning that is requeiring me to use @Suppress("JUnitMalformedDeclaration")
@OptIn(androidx.compose.ui.test.ExperimentalTestApi::class)
@JvmField
@RegisterExtension
@ExperimentalTestApi
val extension: ComposeExtension = createComposeExtension()
Is this to be expected? |
No, this project is solely confined to Android and this includes the Compose support.
This warning can be disregarded, but it definitely is a bug. I've filed #318 for it, thanks for bringing it up! |
When using this together with https://github.com/apter-tech/junit5-robolectric-extension I get the following error:
|
@lukaszkalnik Same here; I'm also trying to use that library to update my Robolectric tests. @mannodermaus Here's a sample test class that ends up throwing the import androidx.compose.material.Text
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.onNodeWithText
import de.mannodermaus.junit5.compose.createComposeExtension
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.extension.RegisterExtension
import tech.apter.junit.jupiter.robolectric.RobolectricExtension
@OptIn(ExperimentalTestApi::class)
@ExtendWith(RobolectricExtension::class)
class SampleTest {
@Suppress("JUnitMalformedDeclaration")
@JvmField
@RegisterExtension
val extension = createComposeExtension()
@Test
fun `Given a string, then it is displayed`() = extension.use {
setContent {
Text("Hello")
}
onNodeWithText("Hello").assertIsDisplayed()
}
} I'm generally really excited for this library because it means that all of my project's UI tests could use JUnit5! This exception in Robolectric tests is a big blocker though |
Thanks for the added information! I have no resources to dedicate to this at the moment, but have created #340 to keep track of it. As this new trace is unrelated to Compose, let's put this ticket to rest and continue over there. 🙇♂️ |
I annotated my tests with the good old
So just to clarify, the current state of using Robolectric Jetpack Compose UI tests with JUnit5 is that there's no working solution at the moment right? Please correct me if I am wrong |
Yes, I haven't tried it in a while but my assumption based on vague memory of past experiences is that Robolectric is not compatible with this library (at least for Compose) If this library could be compatible with robolectric, there might be hope one day for running unit tests (not instrumented) for compose with JUnit 5. Currently, I have a hacky way to run some compose unit tests (not instrumented) in JUnit 5 with this plugin, and without robolectric. But it doesn't work for all components, and it involved a lot of hacky trial and error that I wouldn't recommend to anyone. I decided in the end to just be patient for more updates either from here or from the standard android test library. |
We have a community plugin for robolectric now :D https://github.com/apter-tech/junit5-robolectric-extension |
I would like to use junit 5 to test my jetpack compose project.
A compose test rule is required for setting up the UI and using Testing APIs: (documentation)
This only works for junit 4. Is there any way to use junit 5 with jetpack compose?
The text was updated successfully, but these errors were encountered: