Skip to content

Commit

Permalink
docs: Update README.md (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
warnyul authored Mar 14, 2024
1 parent b57d08b commit ff582ed
Showing 1 changed file with 259 additions and 1 deletion.
260 changes: 259 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,259 @@
# junit5-robolectric-extension
# Junit5 Robolectric Extension (Experimental)

This is an experimental project that aims to bridge the gap between JUnit 5 and Robolectric, providing a way to run your
Android unit tests using the modern JUnit 5 framework while leveraging Robolectric's
in-memory environment.

## Key features

* **JUnit 5 Compatibility:** Run your tests with the latest JUnit 5 features and syntax.

## Current Limitations

* **Parallel Execution:** Parallel test execution is not yet supported. We're actively working on addressing this
limitation in future releases.
* **ClassLoader:** Robolectric's classloader is set before launching the tests. Every test in the suite will use the
Robolectric's classloader, even if it is not annotated with the `RobolectricExtension`.
* **Experimental Status:** This extension is still under development, and its API might change in future versions.

## Installation

1. Add the Maven Central repository to your project's `build.gradle`:

<details open>
<summary>Kotlin</summary>

```kotlin
repositories {
mavenCentral()
}
```

</details>

<details>
<summary>Groovy</summary>

```groovy
repositories {
mavenCentral()
}
```

</details>

2. Enable JUnit Platform Launcher Interceptors and add the dependency to your app or library module's `build.gradle`:

<details open>
<summary>Kotlin</summary>

```kotlin
android {
testOptions {
unitTests {
isIncludeAndroidResources = true
all { test ->
test.useJUnitPlatform()
test.jvmArgs(listOf("-Djunit.platform.launcher.interceptors.enabled=true"))
}
}
}
}

dependencies {
testImplementation("tech.apter.junit.jupiter:robolectric-extension:0.1.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:<latest.release>") // JUnit 5 Jupiter Engine
// Optional dependencies if you want to use different version than used by the extension
testImplementation("org.junit.jupiter:junit-jupiter-api:<latest.release>") // Latest JUnit 5 Jupiter API
testImplementation("org.robolectric:robolectric:<latest.release>") // Latest Robolectric version
}
```

</details>

<details>
<summary>Groovy</summary>

```groovy
android {
testOptions {
unitTests {
includeAndroidResources = true
all {
useJUnitPlatform()
jvmArgs('-Djunit.platform.launcher.interceptors.enabled=true')
}
}
}
}
dependencies {
testImplementation 'tech.apter.junit.jupiter:robolectric-extension:0.1.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:<latest.release>' // Latest JUnit 5 Jupiter Engine
// Optional dependencies if you want to use different versions than used by the extension
testImplementation 'org.junit.jupiter:junit-jupiter-api:<latest.release>' // Latest JUnit 5 Jupiter API
testImplementation 'org.robolectric:robolectric:<latest.release>' // Latest Robolectric version
}
```

</details>

## Basic usage

1. Annotate your test class with `@ExtendWith`. This extension will manage the Robolectric
environment for your tests:

<details open>
<summary>Kotlin</summary>

```kotlin
@ExtendWith(RobolectricExtension::class)
```

</details>

<details>
<summary>Java</summary>

```java
@ExtendWith(RobolectricExtension.class)
```

</details>

2. Utilize the standard JUnit 5 annotations (`@Test`, `@BeforeEach`, `@AfterEach`, etc.) within your test methods. You
could also use `org.jetbrains.kotlin:kotlin-test-junit5` package if you want to.

<details open>
<summary>Kotlin</summary>

```kotlin

import android.app.Application
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertInstanceOf
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.robolectric.annotation.Config
import tech.apter.junit.jupiter.robolectric.RobolectricExtension

@ExtendWith(RobolectricExtension::class)
@Config(application = RobolectricExtensionSelfTest.MyTestApplication::class)
class RobolectricExtensionSelfTest {

@BeforeEach
fun setUp() {
}

@AfterEach
fun tearDown() {
}

@Test
fun shouldInitializeAndBindApplicationAndCallOnCreate() {
val application = ApplicationProvider.getApplicationContext<Context>()
assertInstanceOf(MyTestApplication::class.java, application)
assertTrue((application as MyTestApplication).onCreateWasCalled)
}

companion object {
@BeforeAll
@JvmStatic
fun setUpClass() {
}

@AfterAll
@JvmStatic
fun tearDownClass() {
}
}

class MyTestApplication : Application() {
internal var onCreateWasCalled = false

override fun onCreate() {
this.onCreateWasCalled = true
}
}
}

```

</details>

<details open>
<summary>Java</summary>

```java

import android.app.Application;
import androidx.test.core.app.ApplicationProvider;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions.assertInstanceOf;
import org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.robolectric.annotation.Config;
import tech.apter.junit.jupiter.robolectric.RobolectricExtension;

import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertTrue;

@ExtendWith(RobolectricExtension.class)
@Config(application = RobolectricExtensionSelfTest.MyTestApplication::class)
public class RobolectricExtensionSelfTest {

@BeforeEach
public void setUp() {
}

@AfterEach
public void tearDown() {
}

@Test
public void shouldInitializeAndBindApplicationAndCallOnCreate() {
final Application application = ApplicationProvider.getApplicationContext();
assertInstanceOf(MyTestApplication.class, application);
assertTrue(((MyTestApplication) application).onCreateWasCalled);
}

@BeforeAll
public static void setUpClass() {
}

@AfterAll
public static void tearDownClass() {
}

static class MyTestApplication extends Application {
public boolean onCreateWasCalled = false;

@Override
public void onCreate() {
this.onCreateWasCalled = true;
}
}
}

```

</details>

## Important Notes

* Ensure `isIncludeAndroidResources` is set to true in your testOptions configuration to access Android resources for
your
* JUnit Platform Launcher Interceptors must be enabled (`junit.platform.launcher.interceptors.enabled=true`), otherwise
test instances will not be created by Robolectric's classloader.
* Parallel execution is currently not supported. Run tests sequentially for now.

0 comments on commit ff582ed

Please sign in to comment.