diff --git a/docs/blog/posts/2017-03-01-hermetic-builds.md b/docs/blog/posts/2017-03-01-hermetic-builds.md index 86b2deee3..859c8ec50 100644 --- a/docs/blog/posts/2017-03-01-hermetic-builds.md +++ b/docs/blog/posts/2017-03-01-hermetic-builds.md @@ -137,6 +137,6 @@ Gradle will download all the dependencies you need to run Robolectric and place Add the `.jar` files listed in `build/output/README.txt` as compile-time dependencies. -Place the file called `build/output/robolectric-deps.properties` in your test resources directory. Change the paths as indicated in the comment in that file. +Place the file called `build/output/robolectric-deps.properties` in your test `resources` directory. Change the paths as indicated in the comment in that file. You're all set! Robolectric will now load Android SDKs from the filesystem instead of attempting to download them from Maven Central. diff --git a/docs/blog/posts/2017-03-02-robolectric-3-3-and-roadmap.md b/docs/blog/posts/2017-03-02-robolectric-3-3-and-roadmap.md index af1f470b7..6911f79f1 100644 --- a/docs/blog/posts/2017-03-02-robolectric-3-3-and-roadmap.md +++ b/docs/blog/posts/2017-03-02-robolectric-3-3-and-roadmap.md @@ -10,37 +10,44 @@ slug: robolectric-3-3-and-roadmap Your Robolectric maintainers are pleased to announce the release of [Robolectric 3.3](https://github.com/robolectric/robolectric/releases/tag/robolectric-3.3)! There's been a bunch of activity recently in Robolectric, and we wanted to give a quick update on our thinking about where the project is going. -### Introduction +## Introduction -Robolectric started life in 2010 as a quick hack to allow Android tests to be run on a regular JVM rather than a device or emulator, allowing for fast [TDD cycles](https://en.wikipedia.org/wiki/Test-driven_development#Test-driven_development_cycle). It was mostly developed in brief spurts as needed for testing specific projects. +Robolectric started life in 2010 as a quick hack to allow Android tests to be run on a regular JVM rather than a device or emulator, allowing for fast [TDD cycles](https://en.wikipedia.org/wiki/Test-driven_development#Coding_cycle). It was mostly developed in brief spurts as needed for testing specific projects. Since then, it's been cool to see Robolectric grow with the help of the community, and become quite widely used. It's become a critical part of the test infrastructure of lots of companies and projects. It's rather outgrown the scrappy side-project Robolectric was for much of its life and needs some full-time attention. Here's a high-level view of what we see as the steps ahead toward making Robolectric a trusted, well-supported and dependable Android test framework. In the coming months we’ll be working on: -### Android Fidelity and Trustworthiness +## Android Fidelity and Trustworthiness + Long ago, Robolectric lurked mostly in the shadows: there was no real Android code behind the scenes, only the bits we implemented (which we called Shadows). From 2.0 on, we've had real Android implementations available to use, but lots of old shadow implementations lingered and gave peculiar behavior, plus some bits remained unimplemented or were implemented with behavior that doesn't match that of a device. All this has left Robolectric's trustworthiness in doubt. We're working to match Android's behavior as closely as possible in the spots where we can, and to provide predictable behavior in those places where it's necessary to diverge. -### API Stability -We've had a bit of API thrash and regressions in the past and we're going to work diligently to ease the pain of staying current with robolectric releases. We'll be deprecating APIs before their removal and providing guidance on migration. We do expect a few more large and high-benefit API changes in the coming major releases, but we'll do our best to minimize their impact. We'll be careful to document changes in release notes. +## API Stability + +We've had a bit of API thrash and regressions in the past, and we're going to work diligently to ease the pain of staying current with robolectric releases. We'll be deprecating APIs before their removal and providing guidance on migration. We do expect a few more large and high-benefit API changes in the coming major releases, but we'll do our best to minimize their impact. We'll be careful to document changes in release notes. + +## Documentation -### Documentation Robolectric’s documentation has always been sparse. We're aiming for clear and comprehensive documentation that reveals how the various parts of the Android SDK are simulated by Robolectric, and details extended APIs for testing. -### Performance +## Performance + Robolectric was created to make TDD super fast, so it's disappointing to us too that performance has dipped. We're going to set up a perf suite and spend some time in a profiler and try to squeeze every second out of test startup and run time. -### Toolchain Integration +## Toolchain Integration + We're working on easier project integration for several build systems, tighter integration with Android Studio, and easier and more flexible configuration in general. -### Android SDK Support +## Android SDK Support + As new SDKs and new features are released, we'll make sure Robolectric supports them quickly. -### Community -We're going to do our best to stay on top of bug reports and pull requests. We'll be continuing to develop in the open on GitHub, and we'd love your input on changes and designs. +## Community + +We're going to do our best to stay on top of bug reports and pull requests. We'll be continuing to develop in the open on [GitHub](https://github.com/robolectric/robolectric), and we'd love your input on changes and designs. As always, thanks for your pull requests, bug reports, ideas and questions! _Your Robolectric maintainers,_
-[jongerrish@google.com](mailto:jongerrish@google.com) and [christianw@google.com](mailto:christianw@google.com) \ No newline at end of file +[jongerrish@google.com](mailto:jongerrish@google.com) and [christianw@google.com](mailto:christianw@google.com) diff --git a/docs/blog/posts/2017-11-13-resources-for-real.md b/docs/blog/posts/2017-11-13-resources-for-real.md index c96749821..c52077932 100644 --- a/docs/blog/posts/2017-11-13-resources-for-real.md +++ b/docs/blog/posts/2017-11-13-resources-for-real.md @@ -1,6 +1,8 @@ --- date: 2017-11-13 authors: + - jongerrish + - brettchabot - xian hide: - toc @@ -17,11 +19,9 @@ We're doing this in three separate releases to give you a chance to fix your tes The releases will be: -**3.6:** Resource selection based on transliterated framework code. Configuration properties set from `@Config(qualifiers=...)`. - -**3.7:** Manifest parsing based on transliterated framework code. - -**3.8:** Resource loading from `aapt`-processed binary resource files. +- **3.6:** Resource selection based on transliterated framework code. Configuration properties set from [`@Config(qualifiers)`](../../device-configuration.md). +- **3.7:** Manifest parsing based on transliterated framework code. +- **3.8:** Resource loading from `aapt`-processed binary resource files. We'll keep the changes in each release focused and narrow, and provide lots of notes on migration. Stick with us through this, we think you'll be happy with the improvements. @@ -31,4 +31,4 @@ As always, thanks for your pull requests, bug reports, ideas and questions!  _Your Robolectric maintainers,_
-[jongerrish@google.com](mailto:jongerrish@google.com), [brettchabot@google.com](mailto:brettchabot@google.com), and [christianw@google.com](mailto:christianw@google.com). \ No newline at end of file +[jongerrish@google.com](mailto:jongerrish@google.com), [brettchabot@google.com](mailto:brettchabot@google.com), and [christianw@google.com](mailto:christianw@google.com). diff --git a/docs/blog/posts/2018-05-09-robolectric-4-0-alpha.md b/docs/blog/posts/2018-05-09-robolectric-4-0-alpha.md index 98569ea99..9cce3f7df 100644 --- a/docs/blog/posts/2018-05-09-robolectric-4-0-alpha.md +++ b/docs/blog/posts/2018-05-09-robolectric-4-0-alpha.md @@ -11,23 +11,26 @@ slug: robolectric-4-0-alpha The Robolectric team is super excited to announce the first alpha release of Robolectric 4.0, as well as some new developments in the world of Robolectric and Android testing in general. -### `androidx.test` -We’re collaborating closely with the Android Jetpack testing team to develop common APIs for writing Android tests that can run as both local (JVM-based) and on-device (instrumentation) tests. From 4.0 on, Robolectric will support Jetpack’s [androidx.test](https://developer.android.com/training/testing/) APIs, starting with support for the [`AndroidJUnit4` test runner](https://developer.android.com/training/testing/junit-runner), [`ActivityTestRule`](https://developer.android.com/training/testing/junit-rules), and [Espresso](https://developer.android.com/training/testing/espresso/) for interacting with UI components. +## `androidx.test` + +We’re collaborating closely with the Android Jetpack testing team to develop common APIs for writing Android tests that can run as both local (JVM-based) and on-device (instrumentation) tests. From 4.0 on, Robolectric will support Jetpack’s [`androidx.test`](https://developer.android.com/training/testing/) APIs, starting with support for the [`AndroidJUnit4` test runner](https://developer.android.com/training/testing/junit-runner), [`ActivityTestRule`](https://developer.android.com/training/testing/junit-rules), and [Espresso](https://developer.android.com/training/testing/espresso/) for interacting with UI components. + +### A Robolectric 3.x style test -#### A Robolectric 3.x style test: ```kotlin @RunWith(RobolectricTestRunner::class) class RobolectricTest { @Test fun clickingOnTitle_shouldLaunchEditAction() { val activity = Robolectric.setupActivity(NoteListActivity::class.java) - ShadowView.clickOn(activity.findViewById(R.id.title)); + ShadowView.clickOn(activity.findViewById(R.id.title)) assertThat(ShadowApplication.getInstance().peekNextStartedActivity().action) .isEqualTo("android.intent.action.EDIT") } } ``` -#### Robolectric 4.x/instrumentation test: +### Robolectric 4.x/instrumentation test + ```kotlin @RunWith(AndroidJUnit4::class) class OnDeviceTest { @@ -42,17 +45,17 @@ class OnDeviceTest { As you can see, many of the idioms common in instrumentation tests are now supported by Robolectric tests. In the near future we'll be expanding `androidx.test` support on Robolectric, as well as introducing some Robolectric-originated testing paradigms to traditional instrumentation tests. -### Binary Resources +## Binary Resources In conjunction with Android Studio 3.2, Robolectric can now use resources processed using the Android build toolchain, and loads and handles those resources using the same logic as on an actual Android device. Robolectric's old idiosyncratic resource handling mode is still available for projects not yet using the latest version of the build toolchain. -To enable the use of toolchain-processed resources in Robolectric tests, make sure you're using Android Gradle Plugin version `com.android.tools.build:gradle:3.2.0-alpha14` or higher, and add the following to your `gradle.properties`: +To enable the use of toolchain-processed resources in Robolectric tests, make sure you're using [Android Gradle Plugin](https://developer.android.com/studio/releases/gradle-plugin#updating-plugin) version `com.android.tools.build:gradle:3.2.0-alpha14` or higher, and add the following to your `gradle.properties`: ```properties android.enableUnitTestBinaryResources=true ``` -### Release Notes +## Release Notes Release notes are [available here](https://github.com/robolectric/robolectric/releases/tag/robolectric-4.0-alpha-1). Robolectric 4.0 is currently in alpha release, meaning that it is not yet feature-complete, and APIs are likely to change before the final release. Use with caution. @@ -62,4 +65,4 @@ As always, thanks for your pull requests, bug reports, ideas and questions!  _Your Robolectric maintainers,_
-[jongerrish@google.com](mailto:jongerrish@google.com), [brettchabot@google.com](mailto:brettchabot@google.com), and [christianw@google.com](mailto:christianw@google.com). \ No newline at end of file +[jongerrish@google.com](mailto:jongerrish@google.com), [brettchabot@google.com](mailto:brettchabot@google.com), and [christianw@google.com](mailto:christianw@google.com). diff --git a/docs/blog/posts/2018-10-25-robolectric-4-0.md b/docs/blog/posts/2018-10-25-robolectric-4-0.md index cc369e630..61ee5b0ee 100644 --- a/docs/blog/posts/2018-10-25-robolectric-4-0.md +++ b/docs/blog/posts/2018-10-25-robolectric-4-0.md @@ -11,23 +11,26 @@ slug: robolectric-4-0 Robolectric 4.0 is released! Here's what's new! -### `androidx.test` -The different idioms for testing using Robolectric and instrumentation tests has long been a headache. With today's release of Robolectric 4.0 and `androidx.test` 1.0.0, both testing environments are converging on a set of common test APIs. Robolectric now supports the [`AndroidJUnit4` test runner](https://developer.android.com/training/testing/junit-runner), [`ActivityTestRule`](https://developer.android.com/training/testing/junit-rules), and [Espresso](https://developer.android.com/training/testing/espresso/) for interacting with UI components. +## `androidx.test` + +The different idioms for testing using Robolectric and instrumentation tests have long been a headache. With today's release of Robolectric 4.0 and [`androidx.test`](https://developer.android.com/training/testing/) 1.0.0, both testing environments are converging on a set of common test APIs. Robolectric now supports the [`AndroidJUnit4` test runner](https://developer.android.com/training/testing/junit-runner), [`ActivityTestRule`](https://developer.android.com/training/testing/junit-rules), and [Espresso](https://developer.android.com/training/testing/espresso/) for interacting with UI components. + +### A Robolectric 3.x style test -#### A Robolectric 3.x style test: ```kotlin @RunWith(RobolectricTestRunner::class) class RobolectricTest { @Test fun clickingOnTitle_shouldLaunchEditAction() { val activity = Robolectric.setupActivity(NoteListActivity::class.java) - ShadowView.clickOn(activity.findViewById(R.id.title)); + ShadowView.clickOn(activity.findViewById(R.id.title)) assertThat(ShadowApplication.getInstance().peekNextStartedActivity().action) .isEqualTo("android.intent.action.EDIT") } } ``` -#### Robolectric 4.x/instrumentation test: +### Robolectric 4.x/instrumentation test + ```kotlin @RunWith(AndroidJUnit4::class) class OnDeviceTest { @@ -42,7 +45,7 @@ class OnDeviceTest { As you can see, many of the idioms common in instrumentation tests are now supported by Robolectric tests. In future releases we'll be expanding `androidx.test` support on Robolectric, as well as introducing some Robolectric-originated testing paradigms to traditional instrumentation tests. -### Binary Resources +## Binary Resources In conjunction with Android Studio 3.2, Robolectric can now use resources processed using the Android build toolchain, and loads and handles those resources using the same logic as on an actual Android device. Robolectric's old idiosyncratic resource handling mode is still available for projects not yet using the latest version of the build toolchain, but is now deprecated and will be removed in a future release. @@ -68,11 +71,11 @@ Add this line to your `gradle.properties` (no longer necessary with Android Stud android.enableUnitTestBinaryResources=true ``` -### Migration Tool +## Migration Tool -Robolectric 4.0 contains a number of API changes that may require modifications to your test code. Check out the [migration notes](../../migrating.md/#migrating-to-40) and use the new [automated migration tool](../../automated-migration.md) to help convert your existing tests to be compatible with Robolectric 4.0. +Robolectric 4.0 contains a number of API changes that may require modifications to your test code. Check out the [migration notes](../../migrating.md#migrating-to-40) and use the new [automated migration tool](../../automated-migration.md) to help convert your existing tests to be compatible with Robolectric 4.0. -### Release Notes +## Release Notes Release notes are [available here](https://github.com/robolectric/robolectric/releases/tag/robolectric-4.0). @@ -82,4 +85,4 @@ As always, thanks for your pull requests, bug reports, ideas and questions!  _Your Robolectric maintainers,_
-[jongerrish@google.com](mailto:jongerrish@google.com), [brettchabot@google.com](mailto:brettchabot@google.com), and [christianw@google.com](mailto:christianw@google.com). \ No newline at end of file +[jongerrish@google.com](mailto:jongerrish@google.com), [brettchabot@google.com](mailto:brettchabot@google.com), and [christianw@google.com](mailto:christianw@google.com). diff --git a/docs/blog/posts/2019-06-04-paused-looper.md b/docs/blog/posts/2019-06-04-paused-looper.md index b4298af15..8251f2aa8 100644 --- a/docs/blog/posts/2019-06-04-paused-looper.md +++ b/docs/blog/posts/2019-06-04-paused-looper.md @@ -8,19 +8,20 @@ slug: paused-looper # Improving Robolectric's Looper simulation -**TL;DR: We'd love your feedback on improvements we've made to make Robolectric's Looper behavior -more realistic.** Try it out today by annotating your tests with _@LooperMode(PAUSED)_ and let us +**TL;DR: We'd love your feedback on improvements we've made to make Robolectric's +[`Looper`](https://developer.android.com/reference/android/os/Looper.html) behavior more +realistic.** Try it out today by annotating your tests with +[`@LooperMode(PAUSED)`](../../javadoc/latest/org/robolectric/annotation/LooperMode.html) and let us know your experience! ## Background Unlike on a real device, Robolectric shares a single thread for both UI operations and Test code. -By default, Robolectric will execute tasks posted to Loopers synchronously inline. +By default, Robolectric will execute tasks posted to `Looper`s synchronously inline. This causes Robolectric to execute tasks earlier than they would be on a real device. -While in many cases this has no observable effect it can lead to bugs that are hard to track down. - -Consider the code below. When run on the UI thread on a device, the assertion would pass. +While in many cases this has no observable effect, it can lead to bugs that are hard to track down. +Consider the code below. When run on the UI thread on a device, the assertion would pass. ```java List events = new ArrayList<>(); @@ -31,42 +32,44 @@ events.add("between"); assertThat(events).containsExactly("before", "between", "after").inOrder(); ``` - Robolectric’s default behavior is to process posted code synchronously and immediately, so the assertion fails with `[before, after, between]`, which is clearly incorrect. -Robolectric’ current implementation is notoriously prone to deadlocks, infinite loops and other race - conditions. Robolectric will duplicate each task posted to a Looper into a separate list stored in - `org.roboelectric.util.Scheduler`. The Looper’s set of tasks and the Schedulers can get out of - sync, causing hard-to-diagnose errors. - +Robolectric’s current implementation is notoriously prone to deadlocks, infinite loops and other +race conditions. Robolectric will duplicate each task posted to a `Looper` into a separate list +stored in [`Scheduler`](../../javadoc/latest/org/robolectric/util/Scheduler.html). The `Looper`’s +set of tasks and the `Scheduler`s can get out of sync, causing hard-to-diagnose errors. ## Solution -We’ve re-written Robolectric’s threading model and looper simulation in a way that we hope will +We’ve re-written Robolectric’s threading model and `Looper` simulation in a way that we hope will address the deficiencies of the current behavior. It’s available to try out now by applying a `@LooperMode(PAUSED)` annotation to your test classes or methods. Some of the highlights of the -PAUSED mode vs the existing ‘LEGACY’ mode include: - - -* Tasks posted to the main looper are not automatically executed inline. Similar to the -[ legacy paused IdleState](../../javadoc/4.3/org/robolectric/util/Scheduler.IdleState.html#PAUSED), -tasks posted to the main looper must be explicitly executed via `ShadowLooper` APIs. However, -we’ve made a couple additional improvements in PAUSED mode that make this easier: -* Robolectric will warn users if a test fails with unexecuted tasks in the main looper queue. +[`PAUSED`](../../javadoc/latest/org/robolectric/annotation/LooperMode.Mode.html#PAUSED) mode vs. the +existing [`LEGACY`](../../javadoc/latest/org/robolectric/annotation/LooperMode.Mode.html#LEGACY) +mode include: + +* Tasks posted to the main `Looper` are not automatically executed inline. Similar to the +[legacy `PAUSED` `IdleState`](../../javadoc/latest/org/robolectric/util/Scheduler.IdleState.html#PAUSED), +tasks posted to the main `Looper` must be explicitly executed via +[`ShadowLooper`](../../javadoc/latest/org/robolectric/shadows/ShadowLooper.html) APIs. However, +we’ve made a couple additional improvements in `PAUSED` mode that make this easier: +* Robolectric will warn users if a test fails with unexecuted tasks in the main `Looper` queue. This is a hint that the unexecuted behavior is important for the test case. -* AndroidX Test APIs, like ActivityScenario, FragmentScenario and Espresso will automatically idle - the main looper -* Tasks posted to background loopers are executed in real threads. This will hopefully +* AndroidX Test APIs, like +[`ActivityScenario`](https://developer.android.com/reference/androidx/test/core/app/ActivityScenario), +[`FragmentScenario`](https://developer.android.com/reference/androidx/fragment/app/testing/FragmentScenario) +and [Espresso](https://developer.android.com/training/testing/espresso/) will automatically idle the +main `Looper`. +* Tasks posted to background `Looper`s are executed in real threads. This will hopefully eliminate the need for hacks when trying to test code that asserts that it is running in a -background thread - +background thread. -## Using PAUSED LooperMode +## Using `PAUSED` `LooperMode` -To switch to PAUSED: +To switch to `PAUSED`: -* Use robolectric 4.3. In gradle add +* Use Robolectric 4.3. In Gradle, add: ```groovy dependencies { @@ -74,18 +77,18 @@ To switch to PAUSED: } ``` -* Apply the `LooperMode(PAUSED)` annotation to your test package/class/method -* Convert any background `org.robolectric.util.Scheduler` calls for controlling `Loopers` to -`shadowOf(looper)` -* Recommended, but not mandatory: Convert any foreground `org.robolectric.util.Scheduler` calls -to `shadowOf(getMainLooper())`. The Scheduler APIs will be @deprecated and removed over time. -* Convert any `org.robolectric.android.util.concurrent.RoboExecutorService` usages to -`org.robolectric.android.util.concurrent.PausedExecutorService` or -`org.robolectric.android.util.concurrent.InlineExecutorService` -* Run your tests. If you see test failures like _Main looper has queued unexecuted runnables_, -you may need to insert `shadowOf(getMainLooper()).idle()` calls to your test to -drain the main Looper. Its recommended to step through your test code with a watch set on -`Looper.getMainLooper().getQueue()` to see the status of the looper queue, to determine the +* Apply the `@LooperMode(PAUSED)` annotation to your test package/class/method. +* Convert any background `Scheduler` calls for controlling `Looper`s to +[`shadowOf(looper)`](../../javadoc/latest/org/robolectric/Shadows.html#shadowOf(android.os.Looper)). +* Recommended, but not mandatory: Convert any foreground `Scheduler` calls to +`shadowOf(getMainLooper())`. The `Scheduler` APIs will be deprecated and removed over time. +* Convert any [`RoboExecutorService`](../../javadoc/latest/org/robolectric/android/util/concurrent/RoboExecutorService.html) +usages to [`PausedExecutorService`](../../javadoc/latest/org/robolectric/android/util/concurrent/PausedExecutorService.html) +or [`InlineExecutorService`](../../javadoc/latest/org/robolectric/android/util/concurrent/InlineExecutorService.html). +* Run your tests. If you see test failures like `Main looper has queued unexecuted runnables`, +you may need to insert `shadowOf(getMainLooper()).idle()` calls to your test to drain the main +`Looper`. It's recommended to step through your test code with a watch set on +`Looper.getMainLooper().getQueue()` to see the status of the `Looper` queue, to determine the appropriate point to add a `shadowOf(getMainLooper()).idle()` call. Example: @@ -109,7 +112,7 @@ public class MyTest { // the 'after' task is posted, but has not been executed yet assertThat(events).containsExactly("before", "between").inOrder(); - // execute all tasks posted to main looper + // execute all tasks posted to main Looper shadowOf(getMainLooper()).idle(); assertThat(events).containsExactly("before", "between", "after").inOrder(); @@ -117,17 +120,16 @@ public class MyTest { } ``` - -Take a look at Robolectric’s [ShadowPausedAsyncTaskTest](https://github.com/robolectric/robolectric/blob/master/robolectric/src/test/java/org/robolectric/shadows/ShadowPausedAsyncTaskTest.java) for an example of using PAUSED LooperMode and background tasks. - +Take a look at Robolectric’s [`ShadowPausedAsyncTaskTest`](https://github.com/robolectric/robolectric/blob/master/robolectric/src/test/java/org/robolectric/shadows/ShadowPausedAsyncTaskTest.java) for an example of using `PAUSED` `LooperMode` and background tasks. ## Troubleshooting -* Animations: Use of Animations can cause delayed tasks to be posted to the main looper queue. -You can use the `ShadowLooper.idleFor` or `ShadowLooper.runToEndOfTasks` APIs to execute these tasks. +* Animations: Use of Animations can cause delayed tasks to be posted to the main `Looper` queue. +You can use the [`ShadowLooper.idleFor()`](../../javadoc/latest/org/robolectric/shadows/ShadowLooper.html#idleFor(long,java.util.concurrent.TimeUnit)) +or [`ShadowLooper.runToEndOfTasks()`](../../javadoc/latest/org/robolectric/shadows/ShadowLooper.html#runToEndOfTasks()) APIs to execute these tasks. ## Feedback -Please let us know of any roadblocks to adopting PAUSED LooperMode. +Please let us know of any roadblocks to adopting `PAUSED` `LooperMode`. We’d like to make it the default mode for tests in the next release, and thus your feedback would be - most welcome. +most welcome. diff --git a/docs/blog/posts/2021-09-13-a-memorial-tribute-for-jonathan-gerrish.md b/docs/blog/posts/2021-09-13-a-memorial-tribute-for-jonathan-gerrish.md index b075c605e..8dd92bb1c 100644 --- a/docs/blog/posts/2021-09-13-a-memorial-tribute-for-jonathan-gerrish.md +++ b/docs/blog/posts/2021-09-13-a-memorial-tribute-for-jonathan-gerrish.md @@ -19,8 +19,9 @@ tool that grew to be used by tens of thousands of Android developers. The breadth of the contributions that Jonathan made to the project are too wide to list in this post. He was involved in many high-profile projects such as -revamping PackageManager support and binary resources. He also worked -extensively to get first-class support for Robolectric in Gradle and Bazel. +revamping [`PackageManager`](https://developer.android.com/reference/android/content/pm/PackageManager) +support and binary resources. He also worked extensively to get first-class support +for Robolectric in [Gradle](https://gradle.org/) and [Bazel](https://bazel.build). Jonathan was passionate about continually improving the fidelity of Robolectric to the point [where write-once, run-everywhere](https://medium.com/androiddevelopers/write-once-run-everywhere-tests-on-android-88adb2ba20c5) was possible. This allowed the same test to either be run in Robolectric or any @@ -30,5 +31,5 @@ More importantly, Jonathan had a great spirit and was beloved by friends and family. He was friendly, easy-going, and respectful. He settled near Mariposa, CA to be closer to nature and to enjoy the open space and fresh air. -We miss you dearly Jon. You will always be remembered by the Robolectric +We miss you dearly, Jon. You will always be remembered by the Robolectric community. diff --git a/docs/blog/posts/2021-10-06-sharedTest.md b/docs/blog/posts/2021-10-06-sharedTest.md index 5e802add7..2d1c08945 100644 --- a/docs/blog/posts/2021-10-06-sharedTest.md +++ b/docs/blog/posts/2021-10-06-sharedTest.md @@ -5,12 +5,13 @@ authors: slug: sharedTest --- -# sharedTest pattern: sharing tests and speeding up development +# `sharedTest` pattern: sharing tests and speeding up development -After [Robolectric's 4.0 release][2], Robolectric supports the [`AndroidJUnit4` test runner][3], [`ActivityScenario`][5], and [Espresso][4] for interacting with UI components. As we know, we also can run those tests with an official emulator. This article will show an often overlooked but widely-used pattern called sharedTest to share tests between local and instrumentation tests. This will provide the benefit of fast unit testing while ensuring that tests are high-fidelity by enabling them to be run in an emulator. +After [Robolectric's 4.0 release][2], Robolectric supports the [`AndroidJUnit4` test runner][3], [`ActivityScenario`][5], and [Espresso][4] for interacting with UI components. As we know, we also can run those tests with an official emulator. This article will show an often overlooked but widely-used pattern called `sharedTest` to share tests between local and instrumentation tests. This will provide the benefit of fast unit testing while ensuring that tests are high-fidelity by enabling them to be run in an emulator. ## Using sharedTest steps by steps -The first thing that sharedTest needs is [`AndroidJUnit4` test runner][3]. It is a test runner that supports both Robolectric and [`androidx.test`][13]. There is a sample class, called [`SampleFragmentTest.kt`][14] from [FragmentScenarioSample][15] that uses [`AndroidJUnit4` test runner][3]: + +The first thing that `sharedTest` needs is [`AndroidJUnit4` test runner][3]. It is a test runner that supports both Robolectric and [`androidx.test`][13]. There is a sample class, called [`SampleFragmentTest.kt`][14] from [FragmentScenarioSample][15] that uses [`AndroidJUnit4` test runner][3]: ```kotlin import androidx.fragment.app.testing.launchFragmentInContainer @@ -42,7 +43,7 @@ class SampleFragmentTest { } ``` -The second thing to enable sharedTest is to create a directory called `sharedTest`, at the same directory level with `test` and `androidTest`. The Android Studio doesn't support it, so we should create it manually. [`FragmentScenarioSample`'s `sharedTest` directory][16] is a good example for it. +The second thing to enable `sharedTest` is to create a directory called `sharedTest`, at the same directory level with `test` and `androidTest`. Android Studio doesn't support it, so we should create it manually. [`FragmentScenarioSample`'s `sharedTest` directory][16] is a good example for it. The next step we should do is to add `sharedTest` directory to `test`'s and `androidTest`'s source directory. [`FragmentScenarioSample`'s `build.gradle`][11] is also a good example for it: @@ -58,7 +59,7 @@ sourceSets { } ``` -If you want to share resources too, you can check [Robolectric's PR: Add ctesque common tests to android test][9] that used to reuse tests to improve CI fidelity with sharedTest pattern: +If you want to share resources too, you can check [Robolectric's PR: Add ctesque common tests to android test][9] that used to reuse tests to improve CI fidelity with `sharedTest` pattern: ```groovy sourceSets { @@ -97,27 +98,25 @@ If it finds current running environment has `RobolectricTestRunner`, it will del ## Not only sharing code, but also speeding up development -With sharedTest pattern, we can share test code as much as possible. Is it the only benefit to encourage you to use sharedTest pattern? Not yet. Actually, Robolectric is a simulated Android environment inside a JVM. It has better speed to establish and destroy tests environment, and developers can get test result more quickly. It can help developers to speed up [TDD cycles](https://developer.android.com/training/testing/fundamentals#create-test-iteratively): +With `sharedTest` pattern, we can share test code as much as possible. Is it the only benefit to encourage you to use `sharedTest` pattern? Not yet. Actually, Robolectric is a simulated Android environment inside a JVM. It has better speed to establish and destroy tests environment, and developers can get test result more quickly. It can help developers to speed up [TDD cycles](https://developer.android.com/training/testing/fundamentals#create-test-iteratively): ![The two cycles associated with iterative, test-driven development](https://developer.android.com/images/training/testing/testing-workflow.png) ## References -There are some articles have shown sharedTest pattern, and they are should be mentioned here: - -[Sharing code between local and instrumentation tests by Alex Zhukovich][6] - -[Powerful Approaches to Develop Shared Android Tests by Oleksandr Hrybuk][7] +There are some articles have shown `sharedTest` pattern, and they should be mentioned here: -[Sharing code between unit tests and instrumentation tests on Android by Dan Lew][8] +- [Sharing code between local and instrumentation tests by Alex Zhukovich][6] +- [Powerful Approaches to Develop Shared Android Tests by Oleksandr Hrybuk][7] +- [Sharing code between unit tests and instrumentation tests on Android by Dan Lew][8] -There is an awesome book has introduced sharedTest pattern too: +There is an awesome book has introduced `sharedTest` pattern too: -[Android Test-Driven Development by Tutorials, by Fernando Sproviero, Victoria Gonda and Lance Gleason, Razeware LLC (July 20, 2021)][12] +- [Android Test-Driven Development by Tutorials, by Fernando Sproviero, Victoria Gonda and Lance Gleason, Razeware LLC (July 20, 2021)][12] -There are some Google's projects have used sharedTest pattern to sharing test code: +There are some Google's projects have used `sharedTest` pattern to sharing test code: -[accompanist: [All] Share tests to run on Robolectric & Emulators by chrisbanes][10] +- [accompanist: [All] Share tests to run on Robolectric & Emulators by chrisbanes][10] [1]: https://medium.com/androiddevelopers/write-once-run-everywhere-tests-on-android-88adb2ba20c5 "Write Once, Run Everywhere Tests on Android" [2]: {{ config.site_url }}blog/2018/10/25/robolectric-4-0/ "Robolectric 4.0 release" diff --git a/docs/blog/posts/2022-09-06-Umesh-GSoC-on-ConscryptMode.md b/docs/blog/posts/2022-09-06-Umesh-GSoC-on-ConscryptMode.md index 5bba5b3a5..6b5196613 100644 --- a/docs/blog/posts/2022-09-06-Umesh-GSoC-on-ConscryptMode.md +++ b/docs/blog/posts/2022-09-06-Umesh-GSoC-on-ConscryptMode.md @@ -2,22 +2,24 @@ date: 2022-09-06 authors: - Umesh-01 +hide: + - toc slug: Umesh-GSoC-on-ConscryptMode --- # GSoC 2022 - ConscryptMode -My name is [Umesh Singh](https://github.com/Umesh-01) and I was an open source contributor through Google Summer of Code this year. Google Summer of Code (GSoC) is a program where external participants can contribute to an open source project over a few months. We learn new computer science concepts, how to work on open source repositories, and create real code contributions to projects! +My name is [Umesh Singh](https://github.com/Umesh-01), and I was an open source contributor through Google Summer of Code this year. Google Summer of Code (GSoC) is a program where external participants can contribute to an open source project over a few months. We learn new computer science concepts, how to work on open source repositories, and create real code contributions to projects! My project was `Switching Robolectric from BouncyCastle to Conscrypt as the default security provider`. Robolectric was using [BouncyCastle](https://www.bouncycastle.org/) as the Java Cryptography Extension (JCE) security provider. After the introduction of Android P, Android switched to using [Google Conscrypt](https://source.android.com/docs/core/architecture/modular-system/conscrypt) as the security provider. To be more consistent with Android, Robolectric needed to be updated to use Conscrypt as the default security provider. -When I encountered Robolectric in the GSoC organization list I know it would be a great fit. I had prior experience with Android development and was looking for growth opportunities in this area. Robolectric also offered a lot of learning opportunities in Java, security, and unit testing concepts. +When I encountered Robolectric in the GSoC organization list, I know it would be a great fit. I had prior experience with Android development and was looking for growth opportunities in this area. Robolectric also offered a lot of learning opportunities in Java, security, and unit testing concepts. -The initial approach for this project was to drop BouncyCastle entirely and switch to Conscrypt. This seemed appealing due to the prior issues with BouncyCastle, such as [#5456](https://github.com/robolectric/robolectric/issues/5456). However, we discovered that we couldn't completely switch Robolectric to Conscrypt. Conscrypt only supports the security primitives provided by BoringSSL, and there were some legacy security primitives that were still being used in Android. Because of this we realized that BouncyCastle was needed as the fallback security provider. We settled on having a `@ConscryptMode` annotation that lets users choose whether Conscrypt will be installed or not. When Conscrypt is enabled, Robolectric will search for a requested security feature from Conscrypt first. If it does not support it, the other security providers will be queried. This is more consistent with how Android does it. +The initial approach for this project was to drop BouncyCastle entirely and switch to Conscrypt. This seemed appealing due to the prior issues with BouncyCastle, such as [#5456](https://github.com/robolectric/robolectric/issues/5456). However, we discovered that we couldn't completely switch Robolectric to Conscrypt. Conscrypt only supports the security primitives provided by BoringSSL, and there were some legacy security primitives that were still being used in Android. Because of this, we realized that BouncyCastle was needed as the fallback security provider. We settled on having a [`@ConscryptMode`](../../javadoc/latest/org/robolectric/annotation/ConscryptMode.html) annotation that lets users choose whether Conscrypt will be installed or not. When Conscrypt is enabled, Robolectric will search for a requested security feature from Conscrypt first. If it does not support it, the other security providers will be queried. This is more consistent with how Android does it. -- If ConscryptMode is `ON`, it will install Conscrypt and BouncyCastle. -- If ConscryptMode is `OFF`, it will only install BouncyCastle. +- If [`ConscryptMode.Mode`](../../javadoc/latest/org/robolectric/annotation/ConscryptMode.Mode.html) is [`ON`](../../javadoc/latest/org/robolectric/annotation/ConscryptMode.Mode.html#ON), it will install Conscrypt and BouncyCastle. +- If [`ConscryptMode.Mode`](../../javadoc/latest/org/robolectric/annotation/ConscryptMode.Mode.html) is [`OFF`](../../javadoc/latest/org/robolectric/annotation/ConscryptMode.Mode.html#OFF), it will only install BouncyCastle. I have learned a lot about unit testing, such as how to test whether a piece of code is working according to the expected behavior, and about writing tests for specific scenarios. I have also learned about providing self-explanatory names to methods so that other developers can understand them easily in the future. @@ -25,4 +27,4 @@ I gained experience debugging a large, complex codebase like Robolectric, and ho I have also learned about the tradeoffs that sometimes arise in software projects. For example, Conscrypt does not currently support Mac M1, and to some extent this is out of our control. We were aware of this issue yet decided to move forward with making Conscrypt the default security provider on Linux, Windows, and Mac x86_64. The increased fidelity for these environments outweighs the lack of M1 support. We also have opportunities to collaborate with Conscrypt for Mac M1 support, or explore alternatives like repackaging Conscrypt for Robolectric until Conscrypt supports M1. -You can see my changes here in this [pull request](https://github.com/robolectric/robolectric/pull/7492) and here is a short [documentation](https://github.com/robolectric/robolectric.github.io/pull/122) about it. +You can see my changes here in this [pull request](https://github.com/robolectric/robolectric/pull/7492) and here is a short [documentation](../../configuring.md#conscryptmode) about it. diff --git a/docs/blog/posts/2023-11-11-improving-android-all-downloading.md b/docs/blog/posts/2023-11-11-improving-android-all-downloading.md index bcc5da13c..3181100d3 100644 --- a/docs/blog/posts/2023-11-11-improving-android-all-downloading.md +++ b/docs/blog/posts/2023-11-11-improving-android-all-downloading.md @@ -21,10 +21,10 @@ It does not use any proxies defined by the Gradle build system. In a CI environment, especially in environments used by large companies internally, there are often network restrictions that can cause the aforementioned issues. This article provides some solutions to mitigate these issues as much as possible, -including setting a custom proxy for MavenArtifactFetcher, leveraging Robolectric's offline mode, +including setting a custom proxy for `MavenArtifactFetcher`, leveraging Robolectric's offline mode, and manually fetching the necessary android-all jars before running Robolectric tests. -## Setting custom proxy for MavenArtifactFetcher +## Setting custom proxy for `MavenArtifactFetcher` The first solution is setting a custom proxy for `MavenArtifactFetcher` like the following snippet: @@ -71,8 +71,8 @@ testOptions { } ``` -[Robolectric's configuration documentation](../../configuring.md) contains a detailed description -of these special Robolectric properties, and you can read it for more details. +[Robolectric's configuration documentation](../../configuring.md#system-properties) contains a +detailed description of these special Robolectric properties, and you can read it for more details. ## Leveraging Robolectric's offline mode @@ -162,18 +162,18 @@ The above `build.gradle.kts` is just a sample to download necessary android-all manually before running Robolectric tests. It's easy to maintain. Because Robolectric might add a new android-all jar for a new Android version or modify internal logic to update an existing android-all jar's version, these android-all jars might change -across different Robolectric versions. If you store them in a git repository, -your git repository might become bigger and bigger. If you like this approach, +across different Robolectric versions. If you store them in a Git repository, +your Git repository might become bigger and bigger. If you like this approach, you can store android-all jars in an external repository like [AndroidX](https://android-review.googlesource.com/c/platform/prebuilts/androidx/external/+/2813314). -[Robolectric's configuring documentation](../../configuring.md) contains +[Robolectric's configuring documentation](../../configuring.md#system-properties) contains a detailed description of these special Robolectric properties, and you can read it for details. ## Fetching android-all jars manually before running Robolectric tests -If you don't store android-all jars in your git repository to leverage offline mode, +If you don't store android-all jars in your Git repository to leverage offline mode, and you don't want to modify your system properties for Robolectric in your `build.gradle.kts`, you can try to download android-all jars in a script and download them manually before running any Gradle tasks. @@ -188,4 +188,4 @@ all android-all jars for a specific Robolectric version. Most of these issues are caused by a network issue when downloading necessary android-all jars, and we can fix them or ease them by making android-all jars accessible before running Robolectric tests and letting `MavenArtifactFetcher` use them directly. The above potential solutions are some stable -and recommended solutions for developers to try. Hope it can help you. \ No newline at end of file +and recommended solutions for developers to try. Hope it can help you. diff --git a/docs/blog/posts/2024-02-25-robolectric-2024-gsoc.md b/docs/blog/posts/2024-02-25-robolectric-2024-gsoc.md index 9917acc12..8ddff8159 100644 --- a/docs/blog/posts/2024-02-25-robolectric-2024-gsoc.md +++ b/docs/blog/posts/2024-02-25-robolectric-2024-gsoc.md @@ -12,7 +12,7 @@ organization for the Google Summer of Code (GSOC) 2024! This will provide an opportunity for students interested in Android development to contribute to one of the most widely used testing frameworks for Android. -### What is Robolectric? +## What is Robolectric? For those new to Robolectric, it's a powerful testing framework that allows Android tests to be executed on the JVM instead of an emulator or a real device. @@ -26,17 +26,17 @@ Contributions and improvements to Robolectric make a meaningful impact on the quality of Android testing, and thus improve the quality of the Android ecosystem as a whole. -### The Robolectric GSOC experience +## The Robolectric GSOC experience -This is the second time Robolectric has participated in GSOC (the last time -being in 2022). Students who work on Robolectric will gain a deeper -understanding of the Android framework, JVM internals, and testing -methodologies. Students will also collaborate with the Robolectric maintainers -and other members of the Robolectric community, many of whom are professional -Android developers. Students participating in GSOC will also receive a stipend -from Google! +This is the second time Robolectric has participated in GSOC ([the last time +being in 2022](2022-09-06-Umesh-GSoC-on-ConscryptMode.md)). Students who work +on Robolectric will gain a deeper understanding of the Android framework, JVM +internals, and testing methodologies. Students will also collaborate with the +Robolectric maintainers and other members of the Robolectric community, many +of whom are professional Android developers. Students participating in GSOC +will also receive a stipend from Google! -### Ideal GSOC candidates +## Ideal GSOC candidates Ideally, students applying for Robolectric in GSOC should have a solid grasp of Java fundamentals and some background in Android application development. While @@ -49,10 +49,10 @@ small contribution to Robolectric in order to gain some familiarity with the development environment. Note that time zone differences will be a consideration when reviewing -applications. Because of the limited number of mentors. we would prefer if each +applications. Because of the limited number of mentors. We would prefer if each mentor and host were in a compatible time zone. -### More information +## More information The Robolectric profile for GSOC 2024 can be found [here](https://summerofcode.withgoogle.com/programs/2024/organizations/robolectric). diff --git a/docs/configuring.md b/docs/configuring.md index 366a91fea..8ead69f34 100644 --- a/docs/configuring.md +++ b/docs/configuring.md @@ -246,7 +246,7 @@ For example, to override the Maven repository URL and ID to download the runtime Starting with [Robolectric 4.9](https://github.com/robolectric/robolectric/releases/tag/robolectric-4.9), Robolectric can either use Conscrypt and BouncyCastle or just BouncyCastle as the security provider. In order to migrate tests over time, there is a [`ConscryptMode`](javadoc/latest/org/robolectric/annotation/ConscryptMode.html) annotation that controls whether Conscrypt is loaded as the default security provider with BouncyCastle as backup. -- If `ConscryptMode` is `ON`, it will install Conscrypt and BouncyCastle. -- If `ConscryptMode` is `OFF`, it will only install BouncyCastle. +- If [`ConscryptMode.Mode`](javadoc/latest/org/robolectric/annotation/ConscryptMode.Mode.html) is [`ON`](javadoc/latest/org/robolectric/annotation/ConscryptMode.Mode.html#ON), it will install Conscrypt and BouncyCastle. +- If [`ConscryptMode.Mode`](javadoc/latest/org/robolectric/annotation/ConscryptMode.Mode.html) is [`OFF`](javadoc/latest/org/robolectric/annotation/ConscryptMode.Mode.html#OFF), it will only install BouncyCastle. This is closer to to the way that it works on [real android](https://cs.android.com/android/platform/superproject/+/android-13.0.0_r1:libcore/ojluni/src/main/java/java/security/Security.java;l=134-137). Robolectric will search for a requested security primitive from Conscrypt first. If it does not support it, Robolectric will try BouncyCastle second.