I have been working in a couple of projects where we have created the “same” application in both Android and iOS. In most cases they look and behave the same way (except for the platform specific behavior and UI differences).
As a test developer it is quite hard to create a good automatic test suite that works on both platforms. Both Android and iOS have a couple of different test frameworks that work well but have nothing to do with each other. So you then have to create and maintain two separate test suites, one for Android and one for iOS. They are also written in different languages and with different development tools (IDEs) so even if the applications work the same it is hard to share any code between the tests for the different platforms.
But this is where Appium comes in. From Appiums own website:
Appium is “cross-platform”: it allows you to write tests against multiple platforms (iOS, Android), using the same API. This enables code reuse between iOS and Android testsuites.
So is it really that easy that you just write one testcase and then it magically works on both platforms?
No of course not.
In theory you could create a test that works on both platforms but in practice it is not that easy and it is basically because of two issues.
In most cases you will not be able to find an element using the same identifier in Android and iOS.
E.g. in Android you can find elements by resource id which is not supported in iOS.
In both platforms you can use xpath and classname but they will never be the same in both platforms.
Even though the apps for the different platforms are built to look and behave the same way there are platform specific implementation and design guidelines which could lead to small differences in behavior between the platforms. So to achieve a specific test scenario you may e.g. need to perform some extra steps in one platform compared to the other. Or some steps could maybe differ a bit between the platforms, e.g. a setting is maybe done using a drop-down list in Android while using a slider in iOS.
So does this mean that Appium is not a good solution?
No Appium still solve a lot of the main issues. You have one single development tool (IDE) for your test development. You can use one single programming language for your tests. You can easily share code and content between your tests on the different platforms.
And for the issues above there are solutions.
One general solution, not only related to the issues above, is to use page objects. This is in general a good design pattern for your tests where you create object-oriented classes that correspond to the specific pages in the application under test. This has the advantage that there is a clean separation between the test code and the page specific code such as locators. Because of this it is easier to maintain since only the code in the page-object class need to be updated if the UI changes while the tests that uses that page-object stay intact.
Regarding issue 1 above there are a couple of ways to solve this. One is to use accessibility id which can be used the same way in both Android and iOS. This is of course if they are set to the same values for the corresponding elements in the Android and iOS app (or if you or a fellow team member can set them yourself).
Another solution is to use the annotations @AndroidFindBy and @iOSFindBy. With this you can have the same element in the page object class with both annotations and thereby different locators for the different platforms. Example:
@AndroidFindBy(id = "btn_signIn")
@iOSFindBy(xpath = "//UIAApplication/UIAWindow/UIAButton")
public MobileElement signInButton;
If the app you are testing is performing the exact same way in Android and iOS then the solution above would be enough for you to be able to write a generic test that works on both platforms. But unfortunately that is not always the case.
As described in issue 2 above there are often small deviations between the platforms for performing the same task. Because of this you will need different steps for the different platforms for executing the same scenario. One way to do this is to implement an interface for each page under test. The interface define the methods used in the tests to execute the specific scenario. You can then have different page object files for the Android and the iOS pages that implements the interface methods in their own way. With this you have the solution for both issue 1 (since you have separate page object files for Android and iOS) and issue 2 (since the separate page object files can have different implementation of the same interface method used in the test).
To demonstrate this a bit more clearly I have created an example project with two simple applications for Android and iOS and a corresponding testcase using the “design pattern” described above. You can find the project here: