Hello, and welcome to the second episode of our Appium Tutorial Series. Today we will be installing and running Appium on OS X, as well as writing our first Appium test and running it live on a real device we have connected to our machine. For the duration of this tutorial you will be able to see what is happening on the screen of the device in the window to the right. The first thing we’ll need to do is to grab Appium itself. This can be done by visiting http://appium.io Since we will be writing our tests in Java, we’ll also need an IDE. In this case I will be using IntelliJ IDEA, but you can stick to your IDE of choice. As dependencies for our test, we will need: The Appium Java Client (in this case I’ll be using version 3.3.0) and the Selenium Standalone server too, in this case we will be using version 2.48. And, last but not least, we will need Xcode version 5.1 or higher. We must also not forget to enable UI Automation on our device. This is achieved by navigating to Settings → Developer Options and ticking “Enable UI Automation” Once that has been taken care of, we can actually install and run Appium. The first time we run Appium, we will be confronted with a screen that looks more or less like this. From here, we will be able to start the Appium server and the Appium Inspector, which we will need to find ways to access the app’s UI elements. Before we do that though, we need to spend a minute on configuration. Since we will be running our tests on iOS, make sure iOS is selected as the current target platform. Once we open the iOS Settings tab, we see there is a lot to be customized here. Fortunately, we won’t need to fill in all the fields. One that we definitely need to provide, though, is the App Path. For the purpose of this tutorial, I will be testing the Komoot app, and this means I need the Komoot app .ipa, which fortunately I have right here. Once that has been taken care of, we also need to activate the “Force Device” field. Don’t worry about the actual device, This is used for the device name, so you can actually input whatever you want. Next up is the UDID. This is the unique ID of your connected device. To get to that we just open Xcode… …navigate to the Devices window… …and select the device you want to test on; here, we will find the UDID under the “Identifier” field. We will also need to select the “Full Reset” option, so that after every test our app gets uninstalled… …and the data from the app cleared. This ensures that every time we run a test we have a clean start. We will also need to navigate to the Advanced tab, so we can make sure that the Xcode Path points to our actual installation. That’s it, we are finally ready to launch the Appium server. You will see the logs start to fill up. And, once you get the first “200” response from the server, you can actually run the Inspector. What this will do is actually install the app on the phone and open up the Inspector UI, which you should see in a second. As you can see, the Komoot app has been launched on our phone…
As you can see, the Komoot app has been launched on our phone… …and the Inspector should follow soon. This is the Appium Inspector. What it allows us to do is to select elements of the UI, as these buttons, for example. What we see on the right side of the Appium Inspector is not another live feed from the phone. This is actually a screenshot of the UI of the application that we have just installed. By clicking on elements in this screenshot we can select UI elements from the application. We can also explore the whole UI through the frames on the left. This allows us to select any element in the UI. Once we select an element, this will be highlighted in the screenshot. Once an element has been highlighted, we can see its details in the central frame. We will be using this information to select UI elements and interact with them in our Appium tests. We will be using this information to select UI elements and interact with them in our Appium tests. Now that we have a way to reference elements in the UI and a working Appium instance, we can start writing our tests, so let’s open IDEA and create a new project. In this tutorial we will be using a basic Java project, In this tutorial we will be using a basic Java project, but you can grab the dependencies we have manually downloaded before through Gradle, Maven, or however you prefer. Now that IDEA has created a project for us, we can create our test class. Since we will be using JUnit to run our Appium tests, the first thing we need to do is think about our setup method. What we will be doing in here is, first of all, setting up a connection to the Appium server. What we will be doing in here is, first of all, setting up a connection to the Appium server. Before we can do that though, we need to navigate to “Project Structure” and import the dependencies that we need. The first thing we need to do here is instantiate an IOSDriver. To instantiate the driver we need to pass over two things: first, we need to provide an endpoint. In this case, we will be providing “http://127.0.0.1:4723/wd/hub”, with 4723 being the default Appium port. In this way we will be communicating with our local Appium server. In this way we will be communicating with our local Appium server. That’s not enough, though: we need to provide some capabilities as well, so we first create a DesiredCapabilities object. The only capability we need to set for now is “deviceName”. Again, the device name can be whatever you want. This is kind of weird, but bear with me. Of course we have to take care of an exception here. In this case, we will just throw it, since we don’t need to handle it. So, with the code we have written until now, what will happen is: every time we launch a new test… …we will be establishing a new connection to the Appium server. This is fine, but we also need to end a session after a single test run has ended, otherwise we would be keeping the Appium server busy with a previous stale session. This is easily achieved with a simple teardown method that will run after every test. This is easily achieved with a simple teardown method that will run after every test. For this purpose, we will take advantage of the “@After” annotation.
For this purpose, we will take advantage of the “@After” annotation. Here, the only instruction we need to call is “driver.quit()”. For that to make any sense, we need to have a global driver. At this point we can start writing our test. We will need to use the “@Test” annotation for every test method that we write. Something that is very important is to actually give meaningful names to your test methods. This means we need to be sure about what we are going to do in this method, so let’s take a step back and check the Appium Inspector again. Since we still need to make sure that our current setup is working, we will just perform a very simple action at the beginning: we will be tapping on the “Log in with email” button. Our method will be called “selectLoginWithEmail”. The first thing we will need to do will be to find an element, so we will use “driver.findElement”. And we will need to provide a strategy through which we are going to look for this element. In this case, we will look for the element by name. Basically, we will provide the text value… …of the “Log in with email” button, which you can see up here. We will just copy it and paste it in our code. Once this has been done, we can just go on and click on the element. We could now try and run our test immediately, but if we did that, our test would fail. That’s because we still have the Appium Inspector running. This means the server has an open session that’s already busy. We need to get rid of that before we can run our test. To solve this problem, navigate back to Appium Inspector, close it and restart the server… …then wait for the logs to fill up again… …and then you know you are good to go with your tests. So let’s run our first test. We check what the Appium log is saying… …we’ve seen that a new session has been started. The app is getting installed on our device right now, so we should see it pop up at any moment. There it is. Now we should see the screen change, because we will be performing a click on “Log in with email”. There it is. Our test has succeeded. But did we really just write and run our first Appium test? Sort of, but not really. We have just remote controlled our phone and performed an action on it. We can see that the button was found and clicked correctly because the test succeeded, but we were not checking anything more than that. What we want to do now is to write a real test. Something that reproduces a possible use case and checks against an expected outcome. To do so, let’s restart the Appium Inspector and navigate through the application until we have found a possible use case that we can automate. Let’s focus on what happens after we click on the “Log in with email” button. As you can see, we are taken to a different screen in which we can input email and password, just as you woud expect. What we will be doing here is actually type some invalid email address. And a valid password. Then we will be clicking the “Log in” button. At this point, we will get this error message, so we know what we want to check against if a user is entering an invalid email.
testing app testing run action At this point, we will get this error message, so we know what we want to check against if a user is entering an invalid email.
At this point, we will get this error message, so we know what we want to check against if a user is entering an invalid email. Let’s now switch back to IDEA once more and let’s immediately change the name of our test method, before we forget. Our new name will be “logInWithInvalidEmail” What we need to do now is think about the interactions that we will have to automate. Immediately after clicking this first “Log in with email” button, we will be presented with a new screen containing two text views (or text fields)… …and a further button to confirm that we want to log in with the details we have just provided. Let’s say we need to insert our email credentials, which will be the first thing we need to do after clicking the “Log in with email” button, Then we will also need to insert password credentials. After that is done, we will need to click the login button. We don’t just want to perform these actions and then stop, though: we also want to check against a particular error message (the one we just saw). So here we will have some kind of assertion which asserts that the error message is correct. Now we need to navigate back to the Inspector, select the elements we need to interact with, grab them here in the code and then interact with them accordingly. Let’s now switch back to our inspector… …access the second screen by clicking on “Log in with email” on our phone… …and then by hitting “refresh”. Again, this is not a live feed from the phone, so every time you change screen or something changes on your screen you will need to manually refresh it. And now, as you can see, we can select the email field, password field and login button which we will need. First of all, we will be referencing the email field. First of all, we will be referencing the email field. There is a variety of ways to do this. Right now I am going to show you how to do this through XPath. We won’t be using this XPath query that you see here in the central frame for a simple reason: this query is automatically generated by Appium, and what it is doing is basically starting from the very root of the UI hierarchy… …and going down through each element until it gets to the one we have highlighted… …using indexes on every single element of the chain. What this means is that this query will be extremely brittle, meaning that if anything changes at any point of the chain if any new element is introduced, for example… if any new element is introduced, for example… if any new element is introduced, for example… …the query will break. And that’s in the best scenario, actually… …because of just random chance, you will find yourself with a query that is now selecting another element… …because of just random chance, you will find yourself with a query that is now selecting another element… …because of just random chance, you will find yourself with a query that is now selecting another element… …because it might also be that, due to random chance, you will find yourself with a query that is now selecting another element… …and this might even cause you to waste some time trying to understand why, all of a sudden, your test is doing something it was not supposed to do at all. What I suggest you do instead is: click on the “Copy XML” button. This will copy an XML representation of the UI hierarchy straight to your clipboard. Then, open your browser and navigate to any website that offers you the possibility to test an XPath query against an XML, paste your XML there, and then build your own query. In this case, we will try to grab this UIATextField element… …which is inside a UIATableCell, which itself is inside a UIATableView. If I am lucky enough, there are probably only two UIATableCells on the screen,
If I am lucky enough, there are probably only two UIATableCells on the screen, so basically this one and the one below, containing the password label and the password field. So I can do something like this: I will select all the UIATableCells… …or, actually, just the first one… …and, inside there, I will select the only UIATextField. As we can see, this query returns one element, which is what we are looking for. And that element’s value is “Email”, so if we go back to the inspector we can see we are probably selecting the right element. Now we just copy our query… …go back to our code… …type “driver.findElement(By.xpath(…” and paste the XPath query we have just built. In this case we are not just performing a click on the email field, we want to send an actual string, so we will use the “sendKeys” method. In this case, we will send in “invalid@gmail”, a clearly invalid email address. Of course we can do the same for the rest of the elements that we need to select. So now we can also select our login button… …and click it as well. The last thing we need is the error message, so we will go back to our phone… …simulate the interaction that we are automating…. …and we will go back to the inspector, refresh… and now we can get the error message. After testing our new XPath query, we can proceed to find our last element… …which, in this case, is the alert itself. Once we have the element, we want to grab its text and wrap it into an assertion… …stating that the content of this element must be equal to… …(and here we just paste the expected error message, which is “invalid email”)… Now we should be ready to run our test. What I can tell you though, is that, unfortunately, this will not work. If you go back to our application and you try to log in again… If you go back to our application and you try to log in again… …you can see that it takes a split second for our message to show up. The problem is that here, Appium will try to get the element immediately after we have clicked “Log in”. Appium might be too fast in doing this. What we should do instead, is actually wait for this element to appear… …and set a timeout, so we’ll wait for this element for 15 seconds.. If it appears within 15 seconds, we will then get its text and… …do this assertion to find out if we are correct about the content of the error message. We create a new “WebDriverWait” element… …to which we have to pass the driver and a timeout (we said 15 seconds)… …and we can wait until an expected condition is met… …in this case, the presence of the element located by our XPath query. So what we get from this is a MobileElement… …that we can call “ErrorDialog”… …for which we have waited up to 15 seconds. We can write “errorDialog.getText()” and see if it equals “Invalid email address”. So now we finally run our first Appium test and see how it goes. We can see our app has been launched. Now we click on the “Log in with email” button… …we fill in the first field with our invalid email… …we switch to the second field, send in our password… …then click on the “Log in” button… …and we get our error message, which we check against… and our test succeeds. Congratulations on running your first Appium test on iOS! We hope this video has been useful. If you are interested in running Appium tests in the cloud on multiple devices, please visit us at https://testobject.com