EUnit on Android

I just ran into an issue running EUnit tests for JVM (Android target), where the tests failed on a NullPointerException in the code (i.e. the test itself was fine, but reported that the code I was testing was generating a NPE). I ran the same code from within my Android app and the code works fine.

What I was testing is a custom Java Charset. The implementation of the Charset framework seems pretty platform-specific (as expected) so I’m wondering if the problem would be fixed by running the test on-device rather than on my dev machine?

To clarify, for iOS EBuild provides the nice option to see the EUnit test results in a TableView, but AFAIK we don’t have this option for Android (yet :slight_smile:). I haven’t looked into the code for EUnit much yet, but I’m aware for example that JUnit tests for Android apps needs POJOs, and you need to run integration tests on-device/emulator if you need to access anything Android-specific (contexts, filesystem, etc). This seemed like it could be the same sort of situation.

So 3 questions:

  1. Am I right in suspecting that this sort of test needs to run on-device?
  2. Does the iOS TableView display I’m referring to mean the test actually runs on the iOS device, or does it run on the dev machine and just show the results on the iOS device?
  3. Any chance of getting an Android equivalent of the iOS TableView display?

I would be up for writing the Android-EUnit code and submitting a PR since EUnit is open source. I wasn’t sure if there needed to be changes on the EBuild side as well though (since it unfortunately is not open source yet - I’m looking forward to that one as well :slight_smile:).

Matt,

to clarify, this ia a legit NRE you’re seeing, int;'s not. abut in EUnit, but the actual JVM API you are calling into is simply broken on Windows/Mac (wherever you’re testing), but works on Android/Llinux?

IOW, EUnit it’s working as designed for its part?

If so, possibly. You probably can run tests now, bit you won’t see any results, due to lack of custom UI and lack of Console/stdout on Android. (You’d still see exceptions). I agree tis needs a better solution.

Yeah, we don’t have that yet, but it would be fairly easy to add I imagine. Would you feel like having a stab at adding and contributing that, with pointers from me? If not, I can have a look in the new year (our maybe sooner, if I run out of other stuff over the holidays :wink:

Note that what won’t work is the Fire/Water-integrated capture of test results, as that depends on processing stdout from the debug session, and Android doesn’t offer that (using/processing logcat would, I expect, be too tricky/inconsistent, as it’s too verbose).

I’m not sure I know what that means.

from how I interpret what you wrote, it seems that this is just broken on the Windows/Mac JVm, so yeah.

Yes, it’s custom Listener. Have a look at TableViewTestListener.pas DefaultListener.pas.

What you’d want is a similar infrastructure as in TableViewTestListener.pas, for Android, that would build up a tableview/recuclerview-based activity, launch the UI, and then capture the test results and show it in there GUI instead/in addition to emitting them to stdout. You’d then wanna extend the GetDefaultListener method to return that custom listener, for Android.

Yeah, just has to be done by one of us :wink:

That’d be cool and much appreciated. Let me know what questions you have (I;m sure you will) after looking at the above files.

No, EBuild isn’t involved at all in this But yeah, I shoukld get that opened up soon as well, I’ll look to giving that pro in the new year. Whats your GitHub user account, I can give you early access now if you’re interested (but you won’t need it for this particular task).

—marc

1 Like

Right, not an EUnit issue.

I just meant that unit tests on Android should be Java-only, i.e. not reference anything that needs an underlying Android system, so they can run on the dev system JVM instead of needing to fire up an emulator or push to a device. Now that I think about it, I’m actually not sure if this is required or just the de facto best-practice since testing on Android devices takes an ungodly long time.

Agreed. Now that I think about it, it could be that the Android JVM implements the Charset API differently from the Windows JVM. I couldn’t get any helpful error message aside from NPE, but the NPE may actually have been that I was referencing something in the Android API that doesn’t exist in the Windows API. If that is the case, then yeah it would be really helpful to run EUnit tests on my Android device.

Hmm I tried selecting my device as the target and running the tests, but they didn’t seem to be running on device. The tests ran just as quickly, where I would expect a slight delay from pushing tests to device, and I got the same exceptions as on Windows JVM.

Sure thing. I did scan through the iOS implementation yesterday, but I’ve not done iOS development before, so I’m not 100% fluent with it. I can follow the UI and business logic easily enough but wasn’t sure as to how the tests actually end up on the iOS device (and if this differs from iOS app installs), and how that would be done on Android (i.e. does it need to be installed as an app, in which case it also needs an app manifest, etc?).

Definitely interested and much appreciated!

Curious. thats with an Android-type test project? The IDE wouldn’t even know to not run it locally, affect. I’ll check. Do you run it with Cmd/Ctrl+T or Cmd/Ctrl+R?

Just by nature of it being an iOS app project, its will be run on iOS. at the same will be true for Android, if the project type is set to Android.

All the custom test runner does is instead of just running the tests in main() and letting them emit their results to stdout, it spins up a UIKit application loop (in method RunGUI) and sets a custom listener (TableViewTestListener).

Come to think of it, for Android this will need to be a bit different, as Androids has no main(), and launches right into the MainActivity.

What you’ll wanna to is in the actual project (for now)

  • change the MainActivity to be a table based one (eg using RecyclerView — but you’ll know better whats appropriate here than me)
  • create a custom listener class (like on iOS)
  • pass it to Runner.RunTests(lTests) withListener(Runner.DefaultListener); instead of the default

and implement that Listener (via IEventListener, IEventListenerGUI) to update the table GUI, as test results come in.

Once this all works (and if you can do the recycler view activity without relying on a .layout XML, ideally), we can then later port this down into EUnit as a base class, so that the actual template would just need to be like MainActivity = public class(EUnitTestActrivity) end; or the like.

1 Like

Trie creating an Android test app from template, and both Cmd+R and Cmd-T laugh it in the emulator for me, not locally. Of course I won’t get results for Cmd+T, due to lack of stdout, as mentioned.

Ah. I didn’t know there was an Android-type test project :smile: That answers my questions regarding how to implement the Android EUnit UI as well :smile:

1 Like

Preview… :slight_smile:

Nice!

EUnitTestActivity is working and publicly available on GitHub.

It uses Activity and ListView instead of AppCompatActivity and RecyclerView, all views are built in code instead of XML, and all cross-thread communication is done manually with handlers and messages instead of using RxJava or some other 3rd party library. So only EUnitTestActivity.pas is required - no layout files, no extra project references.

Hopefully someone else finds this helpful. Also, any feedback or PRs are welcome!

Also, here’s a sample project that includes a Test class with ~20k tests.

com.eunit.android.zip (81.8 KB)

Very cool, good job!

For everyone else: this is now integrated with core EUnit and the project templates, for next week’s build.

thanx, Matt!

1 Like