From 8883bc31c96f22fcc0840407b67979766c411358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Muller?= Date: Tue, 29 Oct 2024 06:30:45 +0100 Subject: [PATCH] Create workflow to lint Markdown files (#265) --- .github/workflows/lint-markdown.yml | 27 ++ .markdownlint.jsonc | 12 + README.md | 12 + docs/androidx_test.md | 276 +++++++++--------- docs/automated-migration.md | 3 +- docs/blog/posts/2018-10-25-robolectric-4-0.md | 1 + docs/blog/posts/2021-10-06-sharedTest.md | 35 ++- docs/contributing.md | 1 + docs/extending.md | 13 +- docs/getting-started.md | 2 +- docs/index.md | 10 +- docs/migrating.md | 80 ++--- docs/stylesheets/extra.css | 16 + docs/using-add-on-modules.md | 1 + mkdocs.yml | 2 + 15 files changed, 290 insertions(+), 201 deletions(-) create mode 100644 .github/workflows/lint-markdown.yml create mode 100644 .markdownlint.jsonc diff --git a/.github/workflows/lint-markdown.yml b/.github/workflows/lint-markdown.yml new file mode 100644 index 000000000..ac248245d --- /dev/null +++ b/.github/workflows/lint-markdown.yml @@ -0,0 +1,27 @@ +name: "Lint Markdown" + +on: + merge_group: + pull_request: + push: + branches: [ master ] + +jobs: + lint_project: + name: "Lint Markdown" + runs-on: ubuntu-latest + permissions: + statuses: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Lint Markdown + uses: DavidAnson/markdownlint-cli2-action@v16 + with: + config: ".markdownlint.jsonc" + globs: | + "docs/**/*.md" + "#docs/javadoc/**/*.md" diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc new file mode 100644 index 000000000..63f7189cc --- /dev/null +++ b/.markdownlint.jsonc @@ -0,0 +1,12 @@ +// https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.jsonc +{ + // Line length: https://github.com/DavidAnson/markdownlint/blob/main/doc/md013.md + "MD013": { + "line_length": 120, + "heading_line_length": 120, + "code_block_line_length": 120, + "tables": false + }, + // Code block style: https://github.com/DavidAnson/markdownlint/blob/main/doc/md046.md + "MD046": false +} diff --git a/README.md b/README.md index 60ba63885..5a162d980 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ This repository contains the source of the documentation that lives at [robolect Make sure that you are on the `master` branch, and that it is up to date before making any changes. This is the default branch, so Git should put you there automatically. +### Build the documentation locally + Before submitting a Pull Request, run the documentation locally to check that the content and layout are correct. The documentation is built using [MkDocs](https://www.mkdocs.org/). To do so, make sure that you have [Python 3+ installed](https://www.python.org/downloads/), and then install the required dependencies by running: @@ -20,6 +22,16 @@ Then you can execute the following command to access the documentation locally a mkdocs serve --open ``` +### Validate your Markdown files + +If you modified any Markdown file, we recommend using [`DavidAnson/markdownlint-cli2`](https://github.com/DavidAnson/markdownlint-cli2) to ensure that the formatting rules are respected. + +Once installed, you can run the command below to perform the check. Add the `--fix` option to fix issues that can be addressed automatically. The non-resolved issues will be printed in the console. + +```bash +markdownlint-cli2 "docs/**/*.md" "#docs/javadoc/**/*.md" --config .markdownlint.jsonc +``` + Once your Pull Request is merged, the documentation will be automatically built and deployed by GitHub Actions. ## Javadocs diff --git a/docs/androidx_test.md b/docs/androidx_test.md index bf1e52ed0..9b77cde1e 100644 --- a/docs/androidx_test.md +++ b/docs/androidx_test.md @@ -14,104 +14,104 @@ It is now possible to use the AndroidX test runner in Robolectric tests. If you test runner, please check out the [configuration and plugin API][configuration-plugin-api], and let us know if there are any extension points missing that you require. -**Robolectric** +!!! snippet "Robolectric" -=== "Java" + === "Java" - ```java - import org.robolectric.RobolectricTestRunner; + ```java + import org.robolectric.RobolectricTestRunner; - @RunWith(RobolectricTestRunner.class) - public class SandwichTest { - } - ``` + @RunWith(RobolectricTestRunner.class) + public class SandwichTest { + } + ``` -=== "Kotlin" + === "Kotlin" - ```kotlin - import org.robolectric.RobolectricTestRunner + ```kotlin + import org.robolectric.RobolectricTestRunner - @RunWith(RobolectricTestRunner::class) - class SandwichTest - ``` + @RunWith(RobolectricTestRunner::class) + class SandwichTest + ``` -**AndroidX Test** +!!! snippet "AndroidX Test" -=== "Java" + === "Java" - ```java - import androidx.test.ext.junit.runners.AndroidJUnit4; + ```java + import androidx.test.ext.junit.runners.AndroidJUnit4; - @RunWith(AndroidJUnit4.class) - public class SandwichTest { - } - ``` + @RunWith(AndroidJUnit4.class) + public class SandwichTest { + } + ``` -=== "Kotlin" + === "Kotlin" - ```kotlin - import androidx.test.ext.junit.runners.AndroidJUnit4 + ```kotlin + import androidx.test.ext.junit.runners.AndroidJUnit4 - @RunWith(AndroidJUnit4::class) - class SandwichTest - ``` + @RunWith(AndroidJUnit4::class) + class SandwichTest + ``` ## Application Since most Android code is centric around a [`Context`][context-documentation], getting hold of your application’s context is a typical task for most tests. -**Robolectric** +!!! snippet "Robolectric" -=== "Java" + === "Java" - ```java - import org.robolectric.RuntimeEnvironment; + ```java + import org.robolectric.RuntimeEnvironment; - @Before - void setUp() { - ExampleApplication app = (ExampleApplication) RuntimeEnvironment.application; - app.setLocationProvider(mockLocationProvider); - } - ``` + @Before + void setUp() { + ExampleApplication app = (ExampleApplication) RuntimeEnvironment.application; + app.setLocationProvider(mockLocationProvider); + } + ``` -=== "Kotlin" + === "Kotlin" - ```kotlin - import org.robolectric.RuntimeEnvironment + ```kotlin + import org.robolectric.RuntimeEnvironment - @Before - fun setUp() { - val app = RuntimeEnvironment.application as ExampleApplication - app.setLocationProvider(mockLocationProvider) - } - ``` + @Before + fun setUp() { + val app = RuntimeEnvironment.application as ExampleApplication + app.setLocationProvider(mockLocationProvider) + } + ``` -**AndroidX Test** +!!! snippet "AndroidX Test" -=== "Java" + === "Java" - ```java - import androidx.test.core.app.ApplicationProvider; + ```java + import androidx.test.core.app.ApplicationProvider; - @Before - void setUp() { - ExampleApplication app = ApplicationProvider.getApplicationContext(); - app.setLocationProvider(mockLocationProvider); - } - ``` + @Before + void setUp() { + ExampleApplication app = ApplicationProvider.getApplicationContext(); + app.setLocationProvider(mockLocationProvider); + } + ``` -=== "Kotlin" + === "Kotlin" - ```kotlin - import androidx.test.core.app.ApplicationProvider + ```kotlin + import androidx.test.core.app.ApplicationProvider - @Before - fun setUp() { - val app = ApplicationProvider.getApplicationContext() - app.setLocationProvider(mockLocationProvider) - } - ``` + @Before + fun setUp() { + val app = ApplicationProvider.getApplicationContext() + app.setLocationProvider(mockLocationProvider) + } + ``` ## Activities @@ -131,94 +131,94 @@ places tighter restrictions around lifecycle transitions, namely that invalid or transitions are not possible. If you'd like a [`Rule`][junit-rule]-based equivalent please use [`ActivityScenarioRule`][activity-scenario-rule] instead. -**Robolectric** +!!! snippet "Robolectric" -=== "Java" + === "Java" - ```java - import org.robolectric.Robolectric; - import org.robolectric.android.controller.ActivityController; + ```java + import org.robolectric.Robolectric; + import org.robolectric.android.controller.ActivityController; - public class LocationTrackerActivityTest { - @Test - public void locationListenerShouldBeUnregisteredInCreatedState() { - // GIVEN - ActivityController controller = Robolectric.buildActivity().setup(); - - // WHEN - controller.pause().stop(); - - // THEN - assertThat(controller.get().getLocationListener()).isNull(); - } - } - ``` + public class LocationTrackerActivityTest { + @Test + public void locationListenerShouldBeUnregisteredInCreatedState() { + // GIVEN + ActivityController controller = Robolectric.buildActivity().setup(); -=== "Kotlin" + // WHEN + controller.pause().stop(); - ```kotlin - import org.robolectric.Robolectric + // THEN + assertThat(controller.get().getLocationListener()).isNull(); + } + } + ``` - class LocationTrackerActivityTest { - @Test - fun locationListenerShouldBeUnregisteredInCreatedState() { - // GIVEN - val controller = Robolectric.buildActivity().setup() - - // WHEN - controller.pause().stop() - - // THEN - assertThat(controller.get().locationListener).isNull() - } - } - ``` + === "Kotlin" -**Android X Test** + ```kotlin + import org.robolectric.Robolectric -=== "Java" + class LocationTrackerActivityTest { + @Test + fun locationListenerShouldBeUnregisteredInCreatedState() { + // GIVEN + val controller = Robolectric.buildActivity().setup() - ```java - import androidx.lifecycle.Lifecycle; - import androidx.test.core.app.ActivityScenario; + // WHEN + controller.pause().stop() - public class LocationTrackerActivityTest { - @Test - public void locationListenerShouldBeUnregisteredInCreatedState() { - // GIVEN - ActivityScenario scenario = ActivityScenario.launchActivity(); - - // WHEN - scenario.moveToState(Lifecycle.State.CREATED); - - // THEN - scenario.onActivity(activity -> assertThat(activity.getLocationListener()).isNull()); + // THEN + assertThat(controller.get().locationListener).isNull() + } } - } - ``` + ``` -=== "Kotlin" +!!! snippet "AndroidX Test" - ```kotlin - import androidx.lifecycle.Lifecycle - import androidx.test.core.app.ActivityScenario + === "Java" - class LocationTrackerActivityTest { - @Test - fun locationListenerShouldBeUnregisteredInCreatedState() { - // GIVEN - val scenario = ActivityScenario.launchActivity() - - // WHEN - scenario.moveToState(Lifecycle.State.CREATED) - - // THEN - scenario.onActivity { activity -> - assertThat(activity.locationListener).isNull() + ```java + import androidx.lifecycle.Lifecycle; + import androidx.test.core.app.ActivityScenario; + + public class LocationTrackerActivityTest { + @Test + public void locationListenerShouldBeUnregisteredInCreatedState() { + // GIVEN + ActivityScenario scenario = ActivityScenario.launchActivity(); + + // WHEN + scenario.moveToState(Lifecycle.State.CREATED); + + // THEN + scenario.onActivity(activity -> assertThat(activity.getLocationListener()).isNull()); } } - } - ``` + ``` + + === "Kotlin" + + ```kotlin + import androidx.lifecycle.Lifecycle + import androidx.test.core.app.ActivityScenario + + class LocationTrackerActivityTest { + @Test + fun locationListenerShouldBeUnregisteredInCreatedState() { + // GIVEN + val scenario = ActivityScenario.launchActivity() + + // WHEN + scenario.moveToState(Lifecycle.State.CREATED) + + // THEN + scenario.onActivity { activity -> + assertThat(activity.locationListener).isNull() + } + } + } + ``` Note that in Robolectric since both the test and UI event loop run on the same thread, synchronization is not an issue. [`ActivityScenario.onActivity`][activity-scenario-on-activity] diff --git a/docs/automated-migration.md b/docs/automated-migration.md index a6fe34dcf..090d02637 100644 --- a/docs/automated-migration.md +++ b/docs/automated-migration.md @@ -4,6 +4,8 @@ hide: - toc --- + + # Automated Migration Robolectric provides an automated migration tool to help keep your test suite up to date with @@ -78,7 +80,6 @@ and commit to your source control system. ``` 4. Make sure your code still compiles and commit changes. - 5. Update your project to the new version of Robolectric. The migration tool will make a best effort attempt to adjust the source code, but there might be 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 2668969fc..ba5de55bd 100644 --- a/docs/blog/posts/2018-10-25-robolectric-4-0.md +++ b/docs/blog/posts/2018-10-25-robolectric-4-0.md @@ -7,6 +7,7 @@ authors: slug: robolectric-4-0 --- + # Robolectric 4.0 Released! Robolectric 4.0 is released! Here's what's new! diff --git a/docs/blog/posts/2021-10-06-sharedTest.md b/docs/blog/posts/2021-10-06-sharedTest.md index bbca34bff..3da84424c 100644 --- a/docs/blog/posts/2021-10-06-sharedTest.md +++ b/docs/blog/posts/2021-10-06-sharedTest.md @@ -5,6 +5,8 @@ authors: slug: sharedTest --- + + # `sharedTest` pattern: sharing tests and speeding up development After [Robolectric's 4.0 release][2], Robolectric supports the [`AndroidJUnit4` test runner][3], @@ -142,21 +144,22 @@ There are some Google's projects have used `sharedTest` pattern to sharing test - [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" -[3]: https://developer.android.com/training/testing/junit-runner "AndroidJUnit4 test runner" -[4]: https://developer.android.com/training/testing/espresso/ "Espresso" -[5]: https://developer.android.com/reference/androidx/test/core/app/ActivityScenario "ActivityScenario" -[6]: https://proandroiddev.com/sharing-code-between-local-and-instrumentation-tests-c0b57ebd3200 "Sharing code between local and instrumentation tests by Alex Zhukovich" -[7]: https://medium.com/wirex/powerful-approaches-to-develop-shared-android-tests-15c508e3ce8a "Powerful Approaches to Develop Shared Android Tests by Oleksandr Hrybuk" -[8]: https://blog.danlew.net/2015/11/02/sharing-code-between-unit-tests-and-instrumentation-tests-on-android/ "Sharing code between unit tests and instrumentation tests on Android by Dan Lew" -[9]: https://github.com/robolectric/robolectric/pull/6570 "Add ctesque common tests to android test" -[10]: https://github.com/google/accompanist/pull/180 "[All] Share tests to run on Robolectric & Emulators by chrisbanes" -[11]: https://github.com/android/testing-samples/blob/main/ui/espresso/FragmentScenarioSample/app/build.gradle "FragmentScenarioSample of androidx.test with sharedTest pattern" -[12]: https://www.raywenderlich.com/books/android-test-driven-development-by-tutorials/ "Android Test-Driven Development by Tutorials, by Fernando Sproviero, Victoria Gonda and Lance Gleason, Razeware LLC (July 20, 2021)" -[13]: https://github.com/android/android-test "androidx.test" -[14]: https://github.com/android/testing-samples/blob/main/ui/espresso/FragmentScenarioSample/app/src/sharedTest/java/com/example/android/testing/espresso/fragmentscenario/SampleFragmentTest.kt "SampleFragmentTest.kt of FragmentScenarioSample" -[15]: https://github.com/android/testing-samples/tree/main/ui/espresso/FragmentScenarioSample "FragmentScenarioSample of testing-samples" -[16]: https://github.com/android/testing-samples/tree/main/ui/espresso/FragmentScenarioSample/app/src/sharedTest "sharedTest directory of FragmentScenarioSample" -[17]: https://cs.android.com/androidx/android-test/+/master:ext/junit/java/androidx/test/ext/junit/runners/AndroidJUnit4.java "AndroidJUnit4 source code" -[18]: https://developer.android.com/training/testing/fundamentals#create-test-iteratively "TDD cycles" +[3]: "AndroidJUnit4 test runner" +[4]: "Espresso" +[5]: "ActivityScenario" +[6]: "Sharing code between local and instrumentation tests by Alex Zhukovich" +[7]: "Powerful Approaches to Develop Shared Android Tests by Oleksandr Hrybuk" +[8]: "Sharing code between unit tests and instrumentation tests on Android by Dan Lew" +[9]: "Add ctesque common tests to android test" +[10]: "[All] Share tests to run on Robolectric & Emulators by chrisbanes" +[11]: "FragmentScenarioSample of androidx.test with sharedTest pattern" +[12]: "Android Test-Driven Development by Tutorials, by Fernando Sproviero, Victoria Gonda and Lance Gleason, Razeware LLC (July 20, 2021)" +[13]: "androidx.test" +[14]: "SampleFragmentTest.kt of FragmentScenarioSample" +[15]: "FragmentScenarioSample of testing-samples" +[16]: "sharedTest directory of FragmentScenarioSample" +[17]: "AndroidJUnit4 source code" +[18]: "TDD cycles" diff --git a/docs/contributing.md b/docs/contributing.md index b6ac054b7..a0c75565a 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -1 +1,2 @@ + --8<-- "https://raw.githubusercontent.com/robolectric/robolectric/master/.github/CONTRIBUTING.md" diff --git a/docs/extending.md b/docs/extending.md index 6847d3db2..c8613229d 100644 --- a/docs/extending.md +++ b/docs/extending.md @@ -17,13 +17,13 @@ shadow object to associate with it. Using byte code instrumentation, Robolectric is able to weave in cross-platform fake implementations to substitute for native code and add additional APIs to make testing possible. -### What's in a Name? +## What's in a Name? Why "Shadow"? Shadow objects are not quite [Proxies][proxy-pattern], not quite [Fakes][fake-object], not quite [Mocks or Stubs][mocks-arent-stubs]. Shadows are sometimes hidden, sometimes seen, and can lead you to the real object. At least we didn't call them "sheep", which we were considering. -### Shadow Classes +## Shadow Classes Shadow classes always need a public no-arg constructor so that the Robolectric framework can instantiate them. They are associated to the class that they Shadow with an @@ -48,7 +48,7 @@ Shadow class should extend `ViewGroup`'s superclass' Shadow, `ShadowView`. class ShadowViewGroup : ShadowView ``` -### Methods +## Methods Shadow objects implement methods that have the same signature as the corresponding Android class. Robolectric will invoke the method on a Shadow object when a method with the same signature on the @@ -112,7 +112,7 @@ which they were originally defined. Otherwise, Robolectric's lookup mechanism wi method is defined on `ShadowViewGroup` instead of `ShadowView` then it will not be found at run time even when `setEnabled()` is called on an instance of `ViewGroup`. -### Shadowing Constructors +## Shadowing Constructors Once a Shadow object is instantiated, Robolectric will look for a method named `__constructor__` and annotated with `@Implementation` which has the same arguments as the constructor that was @@ -157,7 +157,7 @@ Robolectric would invoke the following `__constructor__` method that receives a } ``` -### Getting access to the real instance +## Getting access to the real instance Sometimes Shadow classes may want to refer to the object they are shadowing, e.g., to manipulate fields. A Shadow class can achieve this by declaring a field annotated with @@ -276,7 +276,7 @@ Note, by default `Shadows.shadowOf()` method will not work with custom shadows. use [`Shadow.extract()`][shadow-extract] and cast the return value to the custom Shadow class you implemented. -### Building a library of Custom Shadows. +### Building a library of Custom Shadows If you find yourself building a library of custom shadows, you should consider running Robolectric's shadow annotation processor on your library of shadows. This provides a number of benefits such as: @@ -366,6 +366,7 @@ and reduce the bloat in your own codebase. [fake-object]: https://c2.com/cgi/wiki?FakeObject "Fake Object" [implementation-documentation]: javadoc/latest/org/robolectric/annotation/Implementation.html [implements-documentation]: javadoc/latest/org/robolectric/annotation/Implements.html + [kapt-documentation]: https://kotlinlang.org/docs/kapt.html [mockito]: https://site.mockito.org/ [mocks-arent-stubs]: https://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs "Mocks Aren't Stubs" diff --git a/docs/getting-started.md b/docs/getting-started.md index 7ad1e904f..ba4e9afd1 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -208,7 +208,7 @@ If you are not sure if resources are being loaded for a particular library, enab setting the system property `robolectric.logging.enabled = true` and run your tests. You should see lots of output like: -``` +```text Loading resources for 'com.foo' from build/unpacked-libraries/library1... ``` diff --git a/docs/index.md b/docs/index.md index 8aae06500..6274a88a8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,6 +4,8 @@ hide: - toc --- + +
{{ config.site_name }} @@ -55,7 +57,7 @@ Tests run inside the JVM in seconds. With Robolectric you can write tests like t
-- **Test APIs & Isolation** +- **Test APIs & Isolation** --- @@ -71,7 +73,7 @@ Tests run inside the JVM in seconds. With Robolectric you can write tests like t Robolectric provides a [test double][test-double] that's suitable for most unit testing scenarios. -- **No Mocking Frameworks Required** +- **No Mocking Frameworks Required** --- @@ -84,7 +86,7 @@ Tests run inside the JVM in seconds. With Robolectric you can write tests like t instead of the implementation of Android. You can still use a mocking framework along with Robolectric if you like. -- **Run Tests Outside the Emulator** +- **Run Tests Outside the Emulator** --- @@ -93,7 +95,7 @@ Tests run inside the JVM in seconds. With Robolectric you can write tests like t installing steps aren't necessary, reducing test cycles from minutes to seconds so you can iterate quickly and refactor your code with confidence. -- **SDK, Resources, & Native Method Simulation** +- **SDK, Resources, & Native Method Simulation** --- diff --git a/docs/migrating.md b/docs/migrating.md index 1cd95aa7b..54597b1ff 100644 --- a/docs/migrating.md +++ b/docs/migrating.md @@ -100,14 +100,18 @@ code, you may need to fix your tests. Some likely issues include: -* `android.view.InflateException: Binary XML file line #3: Failed to resolve attribute at index 17: - TypedValue{t=0x2/d=0x7f01000e a=-1}`
- This happens when your [`Activity`][activity-documentation] is using a theme that lacks values for - certain attributes used by layouts. Make sure you've specified an appropriate theme for your - activities in your `AndroidManifest`. +!!! quote "" + + > android.view.InflateException: Binary XML file line #3: Failed to resolve attribute at index + > 17: TypedValue{t=0x2/d=0x7f01000e a=-1} + + This happens when your [`Activity`][activity-documentation] is using a theme that lacks values + for certain attributes used by layouts. Make sure you've specified an appropriate theme for your + activities in your `AndroidManifest`. --- + ## Migrating to 3.6 Previously, Robolectric's [`Display`][display-documentation] and @@ -123,6 +127,7 @@ modified for new dimensions, or by pinning them to the old size: --- + ## Migrating to 3.4 ### Dependencies @@ -139,7 +144,7 @@ Shadow pattern as with other framework classes. You can use | 3.3 (was `@Deprecated`) | 3.4 | |---------------------------------------------------------|----------------------------------------------------------------| | `org.robolectric.res.builder.RobolectricPackageManager` | [`ShadowPackageManager`][shadow-package-manager-javadoc] | -| `RuntimeEnvironment.getRobolectricPackageManager() ` | `shadowOf(RuntimeEnvironment.application.getPackageManager())` | +| `RuntimeEnvironment.getRobolectricPackageManager()` | `shadowOf(RuntimeEnvironment.application.getPackageManager())` | If you were using `RuntimeEnvironment.setRobolectricPackageManager()` to install a custom `PackageManager`, you should move your custom behavior to a subclass of @@ -162,6 +167,7 @@ The deprecated and redundant `attach()` method has been removed from --- + ## Migrating to 3.3 ### Moved classes @@ -219,13 +225,14 @@ that we've implemented quite a bit more of `PackageManager`, so you might not ne any longer. Starting with 3.4, `DefaultPackageManager` will be removed and its functionality will be moved into -`ShadowApplicationPackageManager`. +`ShadowApplicationPackageManager`. In general, we recommand using Android Framework APIs where +possible. -| 3.2 (now `@Deprecated`) | 3.3 | -|--------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------| -| `RobolectricPackageManager rpm = RuntimeEnvironment.getRobolectricPackageManager();` | `ShadowPackageManager shadowPackageManager`
` = shadowOf(context.getPackageManager());` | -| `PackageManager packageManager = RuntimeEnvironment.getPackageManager();` | `// Prefer Android Framework APIs where possible`
`PackageManager packageManager = context.getPackageManager();` | -| `RuntimeEnvironment.setRobolectricPackageManager(customPackageManager);` | Use a custom shadow instead! See below. | +| 3.2 (now `@Deprecated`) | 3.3 | +|--------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------| +| `RobolectricPackageManager rpm = RuntimeEnvironment.getRobolectricPackageManager();` | `ShadowPackageManager shadowPackageManager = shadowOf(context.getPackageManager());` | +| `PackageManager packageManager = RuntimeEnvironment.getPackageManager();` | `PackageManager packageManager = context.getPackageManager();` | +| `RuntimeEnvironment.setRobolectricPackageManager(customPackageManager);` | Use a custom shadow instead! See below. | Replace subclasses of `DefaultPackageManager` by a custom shadow (and be a good citizen by contributing your enhancements upstream 🙂): @@ -276,6 +283,7 @@ more [here](getting-started.md). --- + ## Migrating to 3.2 ### Programmatic Configuration @@ -347,6 +355,7 @@ configure all tests, the expected location of the file has been changed. --- + ## Migrating to 3.1 ### Changes @@ -411,6 +420,7 @@ configure all tests, the expected location of the file has been changed. --- + ## Migrating to 3.0 ### New Features @@ -435,29 +445,29 @@ configure all tests, the expected location of the file has been changed. ### Major Changes -| 2.4 | 3.0 | -|------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `Robolectric.application` | `RuntimeEnvironment.application` | -| `Robolectric.shadowOf` | `Shadows.shadowOf` | -| `Robolectric.Reflection.setFinalStaticField` | `ReflectionHelpers.setStaticField` | -| `org.robolectric.Robolectric.Looper` | `org.robolectric.shadows.ShadowLooper.Looper` | -| `org.robolectric.Robolectric.getBackgroundScheduler` | `org.robolectric.Robolectric.getBackgroundThreadScheduler` | -| `org.robolectric.Robolectric.runBackgroundTasks` | `org.robolectric.Robolectric.getBackgroundThreadScheduler().advanceBy(0)` (also `org.robolectric.Robolectric.flushBackgroundThreadScheduler` will run delayed background tasks too) | -| `org.robolectric.Robolectric.getUiThreadScheduler` | `org.robolectric.Robolectric.getForegroundThreadScheduler` | -| `org.robolectric.Robolectric.runUiThreadTasks` | `org.robolectric.shadows.ShadowLooper.runUiThreadTasks` | -| `org.robolectric.Robolectric.runUiThreadTasksIncludingDelayedTasks` | `org.robolectric.shadows.ShadowLooper.runUiThreadTasksIncludingDelayedTasks`
or
`org.robolectric.Robolectric.flushForegroundThreadScheduler` | -| `org.robolectric.Robolectric.getShadowApplication` | `org.robolectric.shadows.ShadowApplication.getInstance` | -| `FragmentTestUtil.startFragment`(v4/v11) | `SupportFragmentTestUtil.startFragment` (v4)
`FragmentTestUtil.startFragment` (v11) | -| `org.robolectric.tester.android.view.TestMenuItem` | `org.robolectric.fakes.RoboMenuItem` | -| `ActivityController.of` | `Robolectric.buildActivity` | -| `org.robolectric.Config.properties` | `robolectric.properties` | -| `@Config(emulateSdk=...)` / `@Config(reportSdk=...)` | `@Config(sdk=...)` | -| `org.robolectric.shadows.ShadowHandler` | `org.robolectric.shadows.ShadowLooper` | -| `org.robolectric.shadows.ShadowSettings.SettingsImpl` | `org.robolectric.shadows.ShadowSettings.ShadowSystem` | -| `Robolectric.packageManager = instance` | `RuntimeEnvironment.setRobolectricPackageManager(instance)` | -| `org.robolectric.res.builder.RobolectricPackageManager`
changed from `class` to `interface` | `org.robolectric.res.builder.DefaultPackageManager` | -| `org.robolectric.shadows.ShadowMenuInflater` | ? | -| `org.robolectric.Robolectric.clickOn` | `org.robolectric.shadows.ShadowView.clickOn` | +| 2.4 | 3.0 | +|---------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Robolectric.application` | `RuntimeEnvironment.application` | +| `Robolectric.shadowOf` | `Shadows.shadowOf` | +| `Robolectric.Reflection.setFinalStaticField` | `ReflectionHelpers.setStaticField` | +| `org.robolectric.Robolectric.Looper` | `org.robolectric.shadows.ShadowLooper.Looper` | +| `org.robolectric.Robolectric.getBackgroundScheduler` | `org.robolectric.Robolectric.getBackgroundThreadScheduler` | +| `org.robolectric.Robolectric.runBackgroundTasks` | `org.robolectric.Robolectric.getBackgroundThreadScheduler().advanceBy(0)` (also `org.robolectric.Robolectric.flushBackgroundThreadScheduler` will run delayed background tasks too) | +| `org.robolectric.Robolectric.getUiThreadScheduler` | `org.robolectric.Robolectric.getForegroundThreadScheduler` | +| `org.robolectric.Robolectric.runUiThreadTasks` | `org.robolectric.shadows.ShadowLooper.runUiThreadTasks` | +| `org.robolectric.Robolectric.runUiThreadTasksIncludingDelayedTasks` | `org.robolectric.shadows.ShadowLooper.runUiThreadTasksIncludingDelayedTasks` or `org.robolectric.Robolectric.flushForegroundThreadScheduler` | +| `org.robolectric.Robolectric.getShadowApplication` | `org.robolectric.shadows.ShadowApplication.getInstance` | +| `FragmentTestUtil.startFragment`(v4/v11) | `SupportFragmentTestUtil.startFragment` (v4) / `FragmentTestUtil.startFragment` (v11) | +| `org.robolectric.tester.android.view.TestMenuItem` | `org.robolectric.fakes.RoboMenuItem` | +| `ActivityController.of` | `Robolectric.buildActivity` | +| `org.robolectric.Config.properties` | `robolectric.properties` | +| `@Config(emulateSdk=...)` / `@Config(reportSdk=...)` | `@Config(sdk=...)` | +| `org.robolectric.shadows.ShadowHandler` | `org.robolectric.shadows.ShadowLooper` | +| `org.robolectric.shadows.ShadowSettings.SettingsImpl` | `org.robolectric.shadows.ShadowSettings.ShadowSystem` | +| `Robolectric.packageManager = instance` | `RuntimeEnvironment.setRobolectricPackageManager(instance)` | +| `org.robolectric.res.builder.RobolectricPackageManager` changed from `class` to `interface` | `org.robolectric.res.builder.DefaultPackageManager` | +| `org.robolectric.shadows.ShadowMenuInflater` | ? | +| `org.robolectric.Robolectric.clickOn` | `org.robolectric.shadows.ShadowView.clickOn` | * `Robolectric.shadowOf_` has been removed. Similar functionality exists in `ShadowExtractor.extract`. diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 5872d051b..a7399d888 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -17,3 +17,19 @@ .md-typeset .grid { grid-template-columns: repeat(auto-fit, minmax(24rem, 1fr)) } + +/* Create a "snippet" admonition type */ +.md-typeset .admonition.snippet, +.md-typeset details.snippet { + border-color: rgb(158, 158, 158); +} +.md-typeset .snippet > .admonition-title, +.md-typeset .snippet > summary { + background-color: rgba(158, 158, 158, 0.1); +} +.md-typeset .snippet > .admonition-title::before, +.md-typeset .snippet > summary::before { + background-color: rgb(158, 158, 158); + -webkit-mask-image: var(--md-admonition-icon--example); + mask-image: var(--md-admonition-icon--example); +} diff --git a/docs/using-add-on-modules.md b/docs/using-add-on-modules.md index 4e773c5ad..7bfcae51b 100644 --- a/docs/using-add-on-modules.md +++ b/docs/using-add-on-modules.md @@ -6,6 +6,7 @@ the base Android SDK are provided by the main Robolectric module. Additional sha dedicated packages. > [!NOTE] +> > - [Robolectric 3.4][robolectric-3.4-release] doesn't include the `shadows-` prefix in the package name (i.e., `org.robolectric:playservices` and `org.robolectric:httpclient`). > - Before Robolectric 3.4, `org.robolectric:playservices` was named `shadow-play-services`. diff --git a/mkdocs.yml b/mkdocs.yml index 18730f7e7..85b976d6c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -48,9 +48,11 @@ extra_css: - stylesheets/extra.css markdown_extensions: + - admonition - attr_list - github-callouts - md_in_html + - pymdownx.details - pymdownx.highlight: anchor_linenums: true line_spans: __span