Appium’s philosophy says that you should be able to use your preferred test practices, frameworks and tools. This, combined with the possibility of writing tests in almost any programming language, made us come up with an interesting test automation solution for our mobile tests.
A BIT OF CONTEXT…
We develop the same app for Android and iOS. Obviously, there are some differences between them, but most of the functionalities are almost identical (especially the critical features).
In our previous mobile test solution we had two different automation frameworks (one for Android and one for iOS), hence there were two different test repos.This was becoming problematic, as they were growing apart and turning more and more unmaintainable, which is not a great solution when you want to update your tests because of UI or functionality changes. Or when a new person joins the team.
SELENIUM FOR MOBILE APPS… APPIUM!
What’s that? A framework that works seamlessly both on Android and iOS? And it also uses the WebDriver protocol that all QA Engineers around here are familiar with? And we can use the programming language we are used to?
Bring it on.
OUR CURRENT TEST AUTOMATION SOLUTION
Since we are able to use the Page-Object pattern, we can create abstraction layers (page objects) to decouple the tests from the item they are testing. We can also create page objects for Android and iOS separately. By doing that, we can tackle the differences between both UIs. We have all our files conveniently and logically organized and easily accessible/readable for future colleagues. In case of UI and functionality updates, we quickly find the affected code.
Below you can see an example of a definition of our LoginPage for Android (in Ruby):
module Android class LoginPage include PageObject text_field(:email, id: 'com.yourapp.qa:id/email') text_field(:password, id: 'com.yourapp.qa:id/password') button(:login, id: 'com.yourapp.qa:id/login_button') def login_with(email, password) login if login_element.when_visible(10).enabled? self.email = email self.password = password login end end end
And an iOS example comes next:
module IOS class LoginPage include PageObject text_field(:email, xpath: '//UIATextField') text_field(:password, xpath: '//UIASecureTextField') button(:login, xpath: '//UIAButton') def login_with(email, password) self.email = email self.browser.find_element(xpath: '//UIATableCell/UIASecureTextField/..').click self.password_element.send_keys(password) login end end end
Below you can see how the same Page Object implementation looks for our web app:
class LoginPage include PageObject text_field(:email, :id => 'user_email') text_field(:password, :id => 'user_password') button(:login, :css => '.btn-primary') def login_with(email, password) self.email = email self.password = password login end end
As you can see, they are all quite similar in structure. Appium lets us forget how to actually click or interact with objects (it drives the apps using the Webdriver protocol). We only need to take care of page object implementations and, of course, the actual set of test ‘steps’. But we are used to do that since it works like our web tests.
Having similar Page Object implementations gives us the possibility to create just one test script which can be run on Android and iOS. For example (Rspec):
describe "Login screen" do it "Logs in" do on(LoginPage).login_with('user_name', 'user_password') end end
Finally, if next week the Android developers change the id of the email text field or add/remove objects from the login screen, we will only need to adjust the LoginPage implementation for Android, leaving the iOS page and the “Login screen” test script intact.
The possibility of implementing page objects for our app screens allows us to keep a well organized repo, in which colleagues can utilize existing page object implementations to build up their new test scripts. In case of UI changes, the affected page object is quickly identified and the change is done in one place.
Appium gives us many new opportunities, like being able to use our preferred test practices, tools, frameworks (Selenium, Page Object Pattern, etc.) and programming languages plus the possibility of running our tests on Android and on iOS (on real devices too!).
Cover photo: TechStage licensed with Creative Commons Attribution-Noncommercial-No Derivative Works 2.0 Generic License