Skip to content
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

Robolectric sample project #18

Closed
wants to merge 29 commits into from
Closed

Conversation

alixwar
Copy link

@alixwar alixwar commented Sep 28, 2017

I added a sample project based on my own setup:

  • Gradle plugin 2.x (latest released)
  • Robolectric (latest released)

There is a Robolectric test in the sample project which executes one line of code but I'm not able to get any code coverage

Steps to reproduce:

  • Run gradlew testDebug
  • Analyze sample-robolectric\build\jacoco\junitPlatformTestDebug.exec (In IntelliJ you can open an .exec-file with ctrl+alt + F6), it shows coverage for all lines of code in de.mannodermaus.gradle.plugins.android_junit5.sample_robolectric.Foo except for the method junit4robolectric()

@alixwar alixwar mentioned this pull request Sep 28, 2017
@alixwar
Copy link
Author

alixwar commented Sep 28, 2017

I've cleaned up the sample now

@alixwar
Copy link
Author

alixwar commented Sep 28, 2017

I improved the sample to include JUnit4 and JUnit5 tests where code coverage is reported correctly

@IgorGanapolsky
Copy link
Contributor

Where is sample-robolectric and where is sample_robolectric? Are they the same module.

@alixwar
Copy link
Author

alixwar commented Oct 10, 2017

Where is sample-robolectric and where is sample_robolectric? Are they the same module.

I'll take a look later tonight! I'm sure it's a mistake on my part. Should be the same

@alixwar
Copy link
Author

alixwar commented Oct 10, 2017

@IgorGanapolsky I think it looks alright. The folder is called sample-robolectric (following the naming convention of the project in general) but the package name is sample_robolectric (dash not permitted). Do you have trouble building the project?

@IgorGanapolsky
Copy link
Contributor

@alixwar You might want to fetch upstream and merge into your repo. Dependency versions were updated yesterday...

@alixwar
Copy link
Author

alixwar commented Oct 10, 2017

@IgorGanapolsky Thanks for telling me, will do that now

@alixwar
Copy link
Author

alixwar commented Oct 10, 2017

@IgorGanapolsky I think it should be fine now

@alixwar
Copy link
Author

alixwar commented Oct 10, 2017

I opened the generated exec file and it's the same result. All tests (JUnit4, JUnit5, Mockito) generate coverage data except for the Robolectric test.

Side note: I managed to f*** up the merge so the changes are quite big. Don't look at the changes, rather follow the steps to reproduce after checking out the project.

@IgorGanapolsky
Copy link
Contributor

Ok, it builds now. One question, what do the tests in sample-robolectric do - just generate coverage report? If that's the case, how to open .exe file on a Mac?

@alixwar
Copy link
Author

alixwar commented Oct 10, 2017

@IgorGanapolsky sample-robolectric contains a source file, Foo.java with some methods (each method is tested by a separate test). The project contains four different types of tests. Jacoco has been configured so running these tests will generate an exec file (code coverage data file). This exec file proves that code coverage is not generated for the Robolectric test as there is no coverage data for the method that is tested by the Robolectric test.

How to open the .exec file on a Mac? I don't know, but your favourite IDE capable of Java code probably supports loading the file and displaying code coverage

@VenomVendor
Copy link

VenomVendor commented Oct 15, 2017

The whole formatting is screwed up from 4 spaces to 2 spaces, was it intentional?
Mostly in this commit
It's hard to find the actual changes now. #18

Ok, found the actul commit, 2-space formatting

@IgorGanapolsky
Copy link
Contributor

It was probably formatted automatically by Android Studio upon commit.

@alixwar
Copy link
Author

alixwar commented Oct 16, 2017

Yeah, I'm not sure why this fork has diverged from the upstreams repo (not a Git wizard) but the point is not to get this PR approved but rather to prove that code coverage is not generated properly even using the latest available version of dependencies

@mannodermaus
Copy link
Owner

Yeah, sorry about that, that reformatting is on me. Since your sample project is quite isolated from the remainder of the repository (i.e. its own module), it should be fairly easy to merge the upstream back into your fork. That being said, I also see this PR as a proof-of-concept for missing code coverage with Robolectric, hence why I haven't merged it in yet.

@joecks
Copy link

joecks commented Oct 26, 2017

I ran the changes and figured out that it is still not possible to run roboloectric tests with junit5, thus using the robolectric test runner. Any suggestions how to solve that?

@alixwar
Copy link
Author

alixwar commented Oct 26, 2017

I ran the changes and figured out that it is still not possible to run roboloectric tests with junit5, thus using the robolectric test runner. Any suggestions how to solve that?

@joecks
Weird. I was able to run the tests without any issues. The only problem for me was the code coverage. How do you run your tests? From an IDE or command line?

@joecks
Copy link

joecks commented Oct 26, 2017

@alixwar Both. The issue is that there is actually no junit5 test here that is ran with the RobolectricTestRunner. So if I am running any Android related action like accessing the Context this test crash due to a not mocked exception

java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.

example is

    @Test
    void junit5codeCoverage() {
        final int result = new Foo().junit5();

        Assert.assertEquals(Looper.getMainLooper().getThread(), Thread.currentThread());

        assertEquals(-1, result);
    }

So I am still not sure how to achieve a combination between robolectric an junit5, any suggestions?

@alixwar
Copy link
Author

alixwar commented Oct 26, 2017

@joecks I was not able to reproduce your problem (Windows 10). This is the result after running the tests from command line:

D:\Repositories\android-junit5\sample-robolectric>..\gradlew clean testDebug
Starting a Gradle Daemon, 1 incompatible Daemon could not be reused, use --status for details

> Configure project :sample-robolectric
NDK is missing a "platforms" directory.
If you are using NDK, verify the ndk.dir is set to a valid NDK directory.  It is currently set to C:\Users\Alix\AppData\Local\Android\Sdk\ndk-bundle.
If you are not using NDK, unset the NDK variable from ANDROID_NDK_HOME or local.properties to remove this warning.

The setTestClassesDir(File) method has been deprecated and is scheduled to be removed in Gradle 5.0. Please use the setTestClassesDirs(FileCollection) method instead.
The getTestClassesDir() method has been deprecated and is scheduled to be removed in Gradle 5.0. Please use the getTestClassesDirs() method instead.
The ConfigurableReport.setDestination(Object) method has been deprecated and is scheduled to be removed in Gradle 5.0. Please use the method ConfigurableReport.setDestination(File) instead.

> Task :sample-robolectric:compileDebugUnitTestJavaWithJavac
warning: unknown enum constant Status.STABLE
  reason: class file for org.apiguardian.api.API$Status not found
warning: unknown enum constant Status.STABLE
2 warnings

> Task :sample-robolectric:junitPlatformTestDebug
WARNING: No manifest file found at .\AndroidManifest.xml.
Falling back to the Android OS resources only.
To remove this warning, annotate your test class with @Config(manifest=Config.NONE).

Test run finished after 2111 ms
[         6 containers found      ]
[         0 containers skipped    ]
[         6 containers started    ]
[         0 containers aborted    ]
[         6 containers successful ]
[         0 containers failed     ]
[         4 tests found           ]
[         0 tests skipped         ]
[         4 tests started         ]
[         0 tests aborted         ]
[         4 tests successful      ]
[         0 tests failed          ]

BUILD SUCCESSFUL in 11s
18 actionable tasks: 17 executed, 1 up-to-date

@joecks
Copy link

joecks commented Oct 27, 2017

Well it is not an issue per se with your branch, but right now it is not very useful, because it misses the usage of Android classes with junit5 tests which I thought was the purpose of this exercise, but maybe I was wrong. You can see the issue by adding this line:

Assert.assertEquals(Looper.getMainLooper().getThread(), Thread.currentThread());

in your junit5codeCoverage test. Or do you mean that you have patched and tested this already? I

@joecks
Copy link

joecks commented Oct 27, 2017

Btw I get this kind of error that is not very surprising:

Failures (1):
  JUnit Jupiter:FooJunit5Tests:junit5codeCoverage()
    MethodSource [className = 'de.mannodermaus.gradle.plugins.android_junit5.sample_robolectric.FooJunit5Tests', methodName = 'junit5codeCoverage', methodParameterTypes = '']
    => java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.

@alixwar
Copy link
Author

alixwar commented Oct 27, 2017

@joecks I think that you have misunderstood the purpose of this branch. The issue that I'm narrowing down is the lack of code coverage when running tests annotated @RunWith(RobolectricTestRunner.class)

The issue you experience sounds like a pure Robolectric runtime environment issue. Maybe @mannodermaus could comment on this?

@joecks
Copy link

joecks commented Oct 27, 2017

Well maybe I have misunderstood the purpose indeed. I was just confused to see that @RunWith(RobolectricTestRunner.class) would not work with junit5, which I thought an robolectric-example module should cover.
But did you managed to run robolectric tests with junit5?

@alixwar
Copy link
Author

alixwar commented Oct 27, 2017

@joecks

But did you managed to run robolectric tests with junit5?

Yes, I can run all the tests in sample-robolectric (as mentioned in the comment). It also works fine running the tests from IntelliJ IDEA (there I even get full code coverage data). The only issue is when I run the tests from command line and inspect the generated ".exec" file where the coverage data is missing for the Robolectric test

@joecks
Copy link

joecks commented Oct 27, 2017

But the robolectric test are run with junit4 and not 5, or?

@alixwar
Copy link
Author

alixwar commented Oct 27, 2017

But the robolectric test are run with junit4 and not 5, or?

JUnit5 using the vintage junit4 runner. To get pure JUnit5 support the Robolectric project needs to implement new extensions. But this is a good point that you have, it is not clear that I meant JUnit5 with the legacy runner

@joecks
Copy link

joecks commented Nov 2, 2017

@mannodermaus do you have any inside on how to implement a junit5 robolectric test runner?

@mannodermaus
Copy link
Owner

mannodermaus commented Nov 2, 2017

You'd basically have to convert the RobolectricTestRunner into a JUnit 5 Extension in order to drive Robolectric tests with the Jupiter TestEngine. There are several extension points to hook into, and that should be enough to migrate over the implementation details of Robolectric. Unfortunately I don't have the insight into the internal architecture of the library, nor the resources to dedicate to these efforts - it would be best to raise awareness over at Alix' issue in their Github!

@erikhuizinga
Copy link

What's the status of this PR and, more importantly, the status of Android + JUnit 5 + Robolectric?

@mannodermaus
Copy link
Owner

This PR used to be a proof-of-concept integration of Robolectric against an outdated version of the android-junit5 plugin. It's up to the Robolectric team to provide full support for JUnit 5, which in turn is dependent on a good proposal for this issue on the JUnit 5 repo first. Until a real integration of the two is managed by the respective team, there won't be a canonical sample project in this repo. I'd also like to link this section from Danny's talk on JUnit 5 at this year's Droidcon, because it gives a great overview of the current state of this topic, too.

@mannodermaus mannodermaus changed the base branch from master to main December 19, 2020 10:06
@vincent-paing
Copy link

After 5 years, Is the state of Roboletric still the same where it doesn't work with Junit5?

@mannodermaus
Copy link
Owner

@vincent-paing The main blocker has been resolved from JUnit 5's end in the meantime, but regardless Robolectric still does not work with it. I gave some context in a pinned issue that you can check out – it also has a link to the Robolectric feature request if you would like to read more or chime in.

With the disparity between the current state of this repo and the timestamp of this POC PR, I'm taking the liberty to also close it down. 🙇‍♂️ I'm crossing my fingers that there'll eventually be a time where Robolectric and JUnit 5 will finally be united in harmony.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants