I have an android app that uses ORMLite/SQLite and I use Robolectric in conjunction with JUnit 4 to allow me to run unit tests in Android Studio and on a Jenkins build server.
Typically I would setup test data in my tests, in the setup, and then run my test scenarios against it but when I tried to do this I started getting issues and exceptions which seemed to be related to files being locked or something and that seems to be a problem others have had... so what I have done up until now is use the create database method in my database helper to create some dummy data which the tests expect to be there.
The problem is my application now needs to plug into a real database and I can't have it setup dummy data when it runs.
If there a way, within my database helper class, to detect if the code is executing on a device or within Robolectric?
This is what works well for me on Robolectric 3.
public static boolean isRoboUnitTest() {
return "robolectric".equals(Build.FINGERPRINT);
}
To start with, I'll say that you shouldn't be putting code to initialise dummy/test data in the normal releasable code and in general you shouldn't need to know from the main app if you're in a robo run or not.
Now moving past the disclaimer and to actually answer your question... One way you could to this is to have a method in your application class like this
public boolean isRoboTestRun() {
return false;
}
Then create a "TestApplication" in the test package that extends your normal application and overrides this method to return true.
It's hacky, but that's because it's not really meant to work that way :)
At some point you have to init OrmLiteSqliteOpenHelper with your Context.
Let assume you do this in your application class in onCreate. So just create Test<your application class name> in your tests sources and override onCreate with empty implementation.
Robolectric will find this class and will use during the tests. More details here.
Related
I'm using the newer way to instantiate Android's UiAutomator that utilizes the InstrumentationRegistry to retrieve the context. The problem is that the new methodology for automation doesn't extend UiAutomatorTestCase or any set of classes that can pass parameter to retrieve via getParams() in other tests. I tried making static variables but they seem to reset after each case.
I was wondering what the newer methodology of adding retrievable parameters was? I also can't seem to find a dupe question which is why I'm posting this...
EDIT:
As another note to the original question, this is a completely automated test suite that has nothing to do with our main application. It still uses the standard UI automator functionality but is a separate code project.
So basically I'm just looking to store results from one #Test scenario to the next #Test scenario that runs in succession.
Thank you
You should use InstrumentationRegistry.getArguments(). It returns the same Bundle of command line arguments as UiAutomatorTestCase.getParams().
I have an android app that uses ORMLite/SQLite and I use Robolectric in conjunction with JUnit 4 to allow me to run unit tests in Android Studio and on a Jenkins build server.
Typically I would setup test data in my tests, in the setup, and then run my test scenarios against it but when I tried to do this I started getting issues and exceptions which seemed to be related to files being locked or something and that seems to be a problem others have had... so what I have done up until now is use the create database method in my database helper to create some dummy data which the tests expect to be there.
The problem is my application now needs to plug into a real database and I can't have it setup dummy data when it runs.
If there a way, within my database helper class, to detect if the code is executing on a device or within Robolectric?
This is what works well for me on Robolectric 3.
public static boolean isRoboUnitTest() {
return "robolectric".equals(Build.FINGERPRINT);
}
To start with, I'll say that you shouldn't be putting code to initialise dummy/test data in the normal releasable code and in general you shouldn't need to know from the main app if you're in a robo run or not.
Now moving past the disclaimer and to actually answer your question... One way you could to this is to have a method in your application class like this
public boolean isRoboTestRun() {
return false;
}
Then create a "TestApplication" in the test package that extends your normal application and overrides this method to return true.
It's hacky, but that's because it's not really meant to work that way :)
At some point you have to init OrmLiteSqliteOpenHelper with your Context.
Let assume you do this in your application class in onCreate. So just create Test<your application class name> in your tests sources and override onCreate with empty implementation.
Robolectric will find this class and will use during the tests. More details here.
I don't know if I'm really rusty with JUnit or their is a concept with Android Testing in particular I'm not familiar with but:
I'm finding it very difficult to understand how my tests get run.
I've created a Test Project based on my main project, and created a class which extends ActivityInstrumentationTestCase2<SinglePaneActivity> and in this Test Case I've implemented setUp(), testPort() and tearDown() methods.
When I run the project as a Android JUnit test it all tests correctly.
However, adding another class extending ServiceTestCase<NativeService> with the same setUp(), testStart() and tearDown() methods implemented, the test isn't performed.
Looking through the documentation I can't find anything which states how the tests are run, I'm assuming since their is no specific setup it done via reflection.
Given that as the case however, I don't understand the documentation on TestSuites or why my Service test case isn't running.
Am I the only one that's finding the usually very well written Android Documentation lacking when it comes to testing?
As #Blackbelt says, the was a warning in the Log's indicating that the Test wasn't running.
My problem was that I had used the constructor auto generated for me by eclipse
public NativeServiceTestCase(Class<NativeService> activityClass) {
And the error was output as a warning in LogCat explaining you need to have an empty argument constructor (But that error wasn't repeated anywhere else with any visibility).
I'm trying to write a batched instrumentation test (using ActivityInstrumentationTestCase2) for a particular Activity where I change the intent each time the test runs. I can do this with a single test, and just loop through stopping and restarting the Activity with the new intent, but this is not what I want. One reason is they really should be separate test runs. The other reason is, I'm using Spoon to generate a report when the tests finish, and the report will rightly think I only ran one test.
What I would like is it to treat a single test as a possibly infinite number of tests, and pass the data into the test each time the test runs.
Unfortunately you can't use Theories because it results in a RuntimeException where the InstrumentationTestRunner can't find my tests. Anyone have any luck with this?
You could always just create a "testing" intent. In order to simulate the relaunching of the application, make a method or several methods that reset all your static variables between tests. Then you can test the classes from within a testing intent inside the application itself using
assert("value", MyClass.myMethod);
resetStatics();
assert(true, MyClass,myMethod);
resetStatics();
I don't know how much this will help you, if at all, but this is how I started writing my own tests.
I recently discovered that you can add a public static Test suite() method to a test class, and when you run just this single test class, InstrumentationTestRunner will run the Test returned by this method. This is helpful because suite() can explicitly call any constructor of your TestCase, including one with parameters.
I have question on the Android API. Android API provides a class called "Instrumentation" class. What is the use of this class? Is the Instrumentation class be used only together with Junit for unit testing.
Can Junit framework can be used to test the methods of the Android API without using the Instrumentation class.
Since Junit package has been included in the Android package, I hope we dont need to use install separately for unit testing.
I would appreciate if you could provide me the information as i can't find these clear information anywhere on the Web.
If we use Junit test framework to test the Android API, can we have test results in the UI format rather than test format.?
Thanks a lot. Apprecite your time.
Regards,
Riyas
The Instrumentation class allows the test case to subscribe to various application events (keypresses, etc), and also programmatically control the UI to enable functional testing of your application.
Therefore, you technically do not need the Instrumentation class for Junit testing if all you are doing is unit testing, and not functional testing of the UI. You could just extend TestCase which does not provide any Instrumentation support.
Here is a link with some fairly good descriptions of the various test classes.
Junit is included within Android and will not need to be installed separately.
Instrumentation API is basically used to inject various kinds of events to the UI so that the application can be stress-tested. You can create an arbitrary event like tapping on the screen and inject it using instrumentation API which is basically like a pseudo event generation.
Instrumentation class is a base class for test frameworks, this provides a very specific functionality, It also provides API to invoke test on device/emulator using ActivityManager Interface via ADB. Also, it can gets back the results to the development machines.
By overriding this class you can enjoy all the context and helper classes you need to run your tests.
Below is a sample implementation, I wrote to explain you the functionality.
public class SampleInstrumentation extends Instrumentation {
#Override
public void onCreate(Bundle arguments) {
super.onCreate(arguments);
Bundle bundle = new Bundle();
bundle.putString("whatisthis","thisiswhat");
finish(0,bundle);
}
}
Manifest:
...
...
</application>
<instrumentation
android:name=".SampleInstrumentation"
android:targetPackage="com.commons"></instrumentation>
</manifest>
Now if you run this command from your development machine.
adb shell am instrument -w -m com.commons/com.commons.SampleInstrumentation
Your instrumentation class onCreate methods get called and you will get some binary encoded response on your console containing data from the bundle you passed to the 'finish' function.
"
whatisthis
thisiswhat
I hope this will make you understand the functionality specific to this base class. For the sake of some motivation, I would like to add that the new android testing framework androidx.test gets compiled with our app (not part of OS and can be modified) directly extends the Instrumentation class (part of Android Framework/OS implementation). Hence you can write your own implementation of a whole new testing framework just by using this class.