In-depth discussion of unit testing in Android_android

Source: Internet
Author: User
Tags documentation throwable
1. Testing for ContentProvider
Before you start writing a case for provider, you should read the instructions for the provider test in the SDK documentation carefully. But just by reading those instructions, you're still not able to write the right case, because you know that the Android documentation is bad, there are some key things that aren't in the documentation, and you know it's not uncommon in Android.
You write a provider case, as follows:
Copy Code code as follows:

public class Demoprovidertest extends Providertestcase2<feedprovider> {
}

There is an error in compiling, it says that ProviderTestCase2 has no implicit constructs, it seems we need a constructor, write a standard junit constructs!
Copy Code code as follows:

public class Demoprovidertest extends Providertestcase2<feedprovider> {
Public feedprovidertest (String name) {
Super (name);
}
}

WTF, there are compiler errors, and more serious! Did ProviderTestCase2 not inherit from TestCase, and with the suggestion of Eclipse, it created a construct with two parameters:
Copy Code code as follows:

public class Demoprovidertest extends Providertestcase2<feedprovider> {
Public feedprovidertest (String name) {
Super (name);
}

Public Demoprovidertest (Class<feedprovider> Providerclass,
String providerauthority) {
Super (Providerclass, providerauthority);
TODO auto-generated Constructor stub
}
}

But the Feedprovidertest (String name) of only one name still has an error, try again without parameters, or not, which means that PROVIDERTESTCASE2 does not have such a constructor, but it doesn't make sense. Because after all, it is inherited from the TestCase Ah! It's amazing and weird!
Since PROVIDERTESTCASE2 does not have a single parameter structure, then only the construction with one parameter can be removed!
Copy Code code as follows:

public class Demoprovidertest extends Providertestcase2<feedprovider> {
Public Demoprovidertest (Class<feedprovider> Providerclass,
String providerauthority) {
Super (Providerclass, providerauthority);
}

public void TestConstructor () throws Throwable {
Assertnotnull ("Can construct resolver", Getmockcontentresolver ());
ContentProvider Provider = Getprovider ();
Assertnotnull ("Can instantiate provider", provider);
}
}

Wrote a basic test, ran it down, got a warning, was reported by the JUnit framework that Demoprovidertest did not define a public constructor TestCase (name) or TestCase (), It's not that I don't define it, but there are compiler errors, because the damned ProviderTestCase2 don't have these two constructs! Damn, we can only add this structure back! But because the parent class does not, you can only reference the two-parameter constructs of the parent class!
Copy Code code as follows:

public class Demoprovidertest extends Providertestcase2<feedprovider> {
Public Demoprovidertest () {
Super (NULL, NULL);
}

Public Demoprovidertest (Class<feedprovider> Providerclass,
String providerauthority) {
Super (Providerclass, providerauthority);
}

public void TestConstructor () throws Throwable {
Assertnotnull ("Can construct resolver", Getmockcontentresolver ());
ContentProvider Provider = Getprovider ();
Assertnotnull ("Can instantiate provider", provider);
}
}

But what does the argument pass? Try it with NULL first! There is a complete error, and there is a NPE when the parent class is initialized, which means null is definitely wrong! Looked at the imposition of a two-parameter construction demoprovidertest (class<feedprovider> providerclass, String providerauthority) and said that a Class object should be passed , and provider's authority, try again!
Copy Code code as follows:

public class Demoprovidertest extends Providertestcase2<feedprovider> {
Public Demoprovidertest () {
Super (Feedprovider.class, authority);
}

Public Demoprovidertest (Class<feedprovider> Providerclass,
String providerauthority) {
Super (Providerclass, providerauthority);
}

public void TestConstructor () throws Throwable {
Assertnotnull ("Can construct resolver", Getmockcontentresolver ());
ContentProvider Provider = Getprovider ();
Assertnotnull ("Can instantiate provider", provider);
}
}

This time okay, but the construction of the two parameters makes no sense, so let a parameter call two parameters:
Copy Code code as follows:

Public Demoprovidertest () {
This (feedprovider.class, authority);
}

Or okay, which means that our case must provide PROVIDERTESTCASE2 with the correct construction parameters!
Plus setup and teardown:
Copy Code code as follows:

@Override
public void SetUp () throws Exception {
Mcontentresolver = Getmockcontentresolver ();
}

@Override
public void Teardown () throws Exception {
Mcontentresolver = null;
}

Run, found TestConstructor Hung, said Getmockcontentresolver () return is NULL, this how can ah, too weird! Consider that it is possible to initialize incorrectly and add a parent class call to setup:
Copy Code code as follows:

@Override
public void SetUp () throws Exception {
Super.setup ();
Mcontentresolver = Getmockcontentresolver ();
}

@Override
public void Teardown () throws Exception {
Super.teardown ();
Mcontentresolver = null;
}

This run again, all okay, explain the method that involves overriding (Override) parent class, want to call the method of the parent class, in order to initialize correctly! The following is the correct full version:
Copy Code code as follows:

public class Demoprovidertest extends Providertestcase2<feedprovider> {
Private Contentresolver Mcontentresolver;

Public Demoprovidertest () {
This (feedprovider.class, authority);
}

Public Demoprovidertest (Class<feedprovider> Providerclass,
String providerauthority) {
Super (Providerclass, providerauthority);
}

@Override
public void SetUp () throws Exception {
Super.setup ();
Mcontentresolver = Getmockcontentresolver ();
}

@Override
public void Teardown () throws Exception {
Super.teardown ();
Mcontentresolver = null;
}

public void TestConstructor () throws Throwable {
Assertnotnull ("Can construct resolver", Getmockcontentresolver ());
ContentProvider Provider = Getprovider ();
Assertnotnull ("Can instantiate provider", provider);
}
}

To sum up, the experience from this example is that for component testing, you inherit from the component test framework below android.test.*, but you need to pass the correct parameters to the test framework for these components, otherwise the case cannot be tested:
Two constructors
Copy Code code as follows:

Public Demoprovidertest () {
This (feedprovider.class, authority);
}

Public Demoprovidertest (Class<feedprovider> Providerclass,
String providerauthority) {
Super (Providerclass, providerauthority);
}

One must not be less, and it is JUnit's specified constructor (with a string, or no arguments) to invoke the construct specified by the test schema to pass the correct arguments to the test framework!
There is the overriding parent class method, must be the parent class method is also called on, otherwise it will not initialize correctly!
But here I have to say that these components test framework is really not good, first of all, the name is confusing, why a 2 Ah! Android is really 2! Also, since as a framework, the initialization of the work should be complete, done thoroughly, so that can be called on the framework. The user should only inherit, do your own things, you should be able to work, like component activity or ContentProvider, in your code, the framework of the initialization work has been done, so you, the successor only need to care about your own initialization work! But the test framework is rotten, the successor should not only care about their initialization but also to ensure that the parent class to pass the correct parameters!
2. Testing for the activity
Also the test of activity is to note the initialization of the part, but for the setup and teardown you do not tune Super also does not matter!
Copy Code code as follows:

public class Exploreractivitytester extends
activityinstrumentationtestcase2<exploreractivity> {
Public Exploreractivitytester () {
This (target_package_name, exploreractivity.class);
}

Public Exploreractivitytester (String pkg, class<exploreractivity> Class1) {
Super (Pkg, Class1);
}

@Override
public void SetUp () {
Minstrumentation = Getinstrumentation ();
}
}

3. Obstacles to Testing
In Android, because of the characteristics of its system architecture, it's particularly difficult to write unit test cases and validate test cases for Android
A. Activity reuse
The reason is that each test package, the test package is also a apk, each package can only inject a target apk, that is, only for a apk content to test, once an operation jumped to apk outside, it is beyond the scope of the test framework control. But the component reuse mechanism is very common in Android, through intent to other applications (APK), invoking other application components to complete an operation, this is the Android feature, is more common! But this gives the unit test case an insurmountable hurdle. The test framework itself is weaker, but when a component is out of the way, the instrumentation cannot control it, and the open source test framework Robutium-solo to some extent solves the question that solo can manipulate any component within a package, In particular, it solves the problem of multiple activity jumps, but as mentioned earlier, because a test apk can only inject one target apk, so once the activity jumps to the application, solo also has no way. This is a problem with no solution. Therefore, the Android test, can only focus on a number of logic layer, API layer, data and provider,service, and other than the surface operation of the code! For the surface activity jumps and jumps the situation, can only do partial test, or uses the mockobject to solve, but this usually loses the test the own significance, because spends a lot of time to create Mockobject, is not worth!
B. Actionbar is not clickable
There is a very disgusting problem is that the activity of the Actionbar can not directly click, really do not understand what Google is doing, to make a new thing, even test framework inside does not support operation! The thought of clicking Actionbar can only be clicked by solo to screen coordinates, which is very difficult to transplant and maintain!
When it comes to operations, we also have to say that the original framework instrumentation support operation is very small, and bad use, it can only distribute KeyEvent events, many cases are not used, such as a dialog box, want to click Okay or cancel, it is very troublesome, Again, if you want to click on a ListView in one of the words is also very troublesome! The same third party Robotium-solo framework is much better, it has a good encapsulation, through the Solo.clickontext () can easily click on the screen with this text view. Its internal implementation is through the view display tree, according to the tag (text) to find the relevant view, and then send the Click event! This also explains why solo can not click on Actionbar, because Actionbar is not in the activity view, it is like StatusBar, belongs to the system level thing!
c. StatusBar belongs to settings.apk
It is hard to imagine, everywhere StatusBar unexpectedly belong to the settings, only injected the settings of the package to StatusBar operation. So while StatusBar has something related to your apk (such as hints), you still can't manipulate it directly unless you're writing a test kit that's specifically injected into settings.apk!
4. Security concern
The code that is tested (instrumentation and Testrunner) is also in the form of a apk that can inject any target apk and then manipulate it and even retrieve its resources and data. That brings up the security problem! A apk with a test code can be used as an application, once running on a mobile phone, but can operate on any one application.
In fact, this is not a problem, if the application market can be the application of developers upload rigorous testing and audit. But now the problem is whether Google Play or other markets are not testing, so it will allow the bad people to take advantage!
In fact, the key problem here is that Android manufacturers do not blindly pursue the number! Apple's App Store is the best that Apple has come up with when it comes to selling apps. Android is just a copycat, so you develop slowly, not many, not enough quality, poor income, is normal, because you are a follower, you start late! For manufacturers, you have no way to control the number of a sudden to make tens of thousands of applications, this will take time, but, at least, you can strictly control the quality Ah! You can do to upload the application of rigorous testing, which is responsible for the user, but also responsible for their own Ah! So whether it's a device or an app, it's Apple's premium, and Android is always going to be a little bit more expensive, so you can look at Apple's stuff at a high price, Android is cheap, and of course the price is the only advantage of Android! Now the society is a penny a penny, cheap natural there is no good goods!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.