 So, we have got the next speaker, he is Gaurav Singh from Metta, he is working in Facebook London office. So the topic he is going to cover is Hello Expresso, the start with the Android gray box automations. So I will welcome the Gaurav Singh on the stage. Sure. Thanks Sahil. Welcome everyone, morning, afternoon or evening wherever you are joining from. This is a pretty long session and I hope you're going to like it. We are going to discuss a lot about Espresso as a framework, we'll understand the theory about it and lots more. This is not exactly a live tutorial, it's a sort of watch party so I'll be watching it along with you in this recording. Watch out for some quizzes at the end of like every section and people who do great in the quiz. I promise to meet you in person and probably sponsor a beer for you either in London or in Bangalore wherever we are. So yeah, let me start the recording and let's get it started. Hello everyone. I hope all of you are having a great Selenium conference and having a lot of fun learning about testing, test automation and all the cool things that Selenium has to offer. Welcome to my talk on Hello Espresso. Start with Android Greybox Automation. Let's get started. Before we begin, a quick word of intro about who am I. My name is Gaurav Singh, I'm a software engineer, I'm very passionate about software testing and test automation. I have been in this space for close to 10 years and I love every bit of it. I am a test automation university instructor with couple of courses. I have previously spoken at Selenium, Appium and Automation Guild and they have all been great experiences. I also maintain a blog on software engineering and testing at automationhacks.io and I do maintain a newsletter. So you have a newsletter.automationhacks.io to refer to it. In general, if you want to reach out to me after this talk, you can search for at automation hacks on LinkedIn or Twitter and I'll be more than happy to connect with you and learn from you and as well as share my experience. So before we begin, let's set some expectations. Who is this session actually for? The main audience that I want to write this session for is someone who is starting out with Espresso. So a noob, people who are from gaming backgrounds will connect to this term. I'm looking at people who are motivated to write into an Android UI test and if not hopefully convince some of you to write bit more automation. This talk is primarily for software and test engineers but people from other engineering backgrounds might also get value out of it. It's generally for people who are already familiar with Java and Android, but if you're coming from a different background, I hope the syntax would not be too unfriendly and you'll be able to follow. Definitely let me know in the comments in case something is unclear and I'll be more than happy to work with you on that. So what will we cover as part of this tutorial? We will look over what Espresso is, how is it better or what kind of problems we can solve with it when we compare it with some other frameworks. I come from an Appium background for mobile automation, so I'll naturally make some comparisons but I hope end-to-end testing is a wide space and you can relate to it from any other background that you might be coming from, whether it be Selenium as well. We'll look at what is an Espresso test, how is it structured and then we will start to dive into how to automate common Android components like lists, intents, we'll understand what is this thing called as idling resources and what do we mean when we look at automating webviews. We have lots to cover and a lot of fun along the way, so hopefully you will find this section as engaging and fun as I found it when I started to learn about this. Again, a bit of logistics around the talk, so naturally the question is where can I find the code for this, it's all on GitHub, so if you go to automation hacks slash testing samples you would be able to find all the applications and the test code that we will be using. The testing samples is actually a repository from Google, I have forked it into my own repo to make it a bit more deterministic but you can feel free to check out the main repo, it's constantly updated with every version of Android, they actually run these tests whenever they are looking to launch a new version of Android or Espresso. If you prefer to read blogs, I do happen to have written blogs on this topic, so you can go to automation hacks.io and just search for Espresso, you should be able to find these five blogs that have written on the topic. These blogs cover the same content with some more background but we will cover most of it in this tutorial. Going forward, if you want to just search for Espresso related blogs, you can go on the site, go to posts by tag and just search for Espresso as well. Wonderful. So now with all of that out of the way, we can go right into what Espresso is and dive deep into it. Naturally whenever we are learning a new framework, we have to understand what it is. So for people who are new to it, it's a UI automation library, it's primarily for Android, it is made by Google and Google is... Oh, could you please start your camera please? Some of the engineers who are contributing to it, but it is open source. So it's wide open and there are other engineers as well who are spending their time submitting patches, adding new features and whatnot. It's unique in that it offers both black box as well as white box support for Android automation. We'll see some examples of what it means, but essentially if you want to use it as a black box automation library, you can. But if you want to also make use of Android internals, it has support for that. You have access to Android instrumentation, which is great. We'll see some examples of it in further sections. But before we go actually into it, I want to create some motivation for it, for why Espresso and why not a different framework. So naturally, any complex problem in software engineering, if I put this question right, you are always or in most cases you say it depends on the context. And of course, this is also context driven. Espresso has some really neat features and has some tradeoffs like any other framework. So it has a really nice, easy and concise API. We will see examples of what it means. These tests run really fast and it automatically weights in most of the cases. In some cases they do need a bit of help and we will see that in idling resources. The tests are really close to your application code base. And this in my opinion is a big advantage because your developers can see the application code and the test code right side by side. So as soon as this change a view or a component, it's very easy for them to get local feedback right in their editor. And they can just quickly, you know, fix the test and whatnot. It has very low barrier, very less friction for them to actually write tests. And coming to my next point, you can actually write tests in Kotlin and Java, which is the language in which Android development is primarily done, which is again wonderful. And lastly, it is maintained by Google. It is open source and has a great, well maintained documentation, good community support. So you can be rest assured that this framework will live. It will keep on getting patches. And so if you invest in it, you are probably in safe hands. Awesome that that of the way we can just understand a bit about the technical implementation now. So let's understand how to set it up. So so espresso is primarily written in the same repository in which you have your Android app code base. In most of the cases, most Android apps use Gradle as a build tool. So you can just specify espresso core as an Android test implementation. You can specify the version of it, which makes sense, either an alpha version or the stable version. Additionally, we also add the test runner and some rules. And we'll see some examples of this. But that's about it. We need to add this in the apps build out Gradle. Notice that in Android, you have a couple of build out gradles at the root and the app level. So this needs to go into the apps build out Gradle. Next, we also need to specify that we'll use Android J unit runner for these examples. So we need to add this as an instrumentation runner. How you do it is you add it in the default config section in your build out Gradle. So and I'll show you this in the actual file in just a moment. But within Android, you can specify test instrumentation runner and specify this class with specifies Android J unit runner as the preferred choice that we are going to use. So now we can just take a look at what is an actual and espresso test made off, right? What are the nuts and bolts? What are the basic API? I know I've been saying it has a nice concise API. So it's about time we take a look at some example of it. So if when you hear espresso, you'll see some common terms flying around, you'll hear matcher, you'll see action and assertion. Some of them might seem familiar or might not. But don't worry, we'll understand what it means in just a moment. So when you take a look at any typical espresso test, it has three main parts. There is an on view, or a section where you actually find the element you want to do some action on, you perform some action on it. And then finally, you check what happened to my app? Is it in the desired state or not? So I described three main parts, right? You find an element, you perform an action and you check. So let's take a look at the finding the element part. So in espresso, when you have to find any element in a view, you typically use the on view method. And it expects a method in the view matcher class. So view matcher is basically a hamcrest matcher. If you're not familiar with hamcrest matchers, don't worry, we will see some examples of it in further sections and I'll share some links that you can read later on to understand the syntax. It's a very powerful way of specifying conditions based on which you want to find elements. Once you've found the element, you want to obviously perform some action on it. So you specify methods from the view action class, something like click, send type text and stuff. We will see some examples of it. And once you've found it, you naturally want to just check is my application in the desired state or did a new element show up with a certain property. So you use the check method and you pass methods from the view assertion class. So let's see an actual example of this. So this is how your actual test looks like. So you have the on view method and let's say I want to find a view with an ID my view. So you have you specify the width ID matcher, and you specify r dot ID dot my view r dot ID is an Android syntax to find any element from your resource classes. So if you if we'll see if you type it in Android Studio, you'll be able to find elements this way. Next, here we will perform a simple click. So we pass a click method. And finally, we want to see that, okay, is this element now displayed? So you use the matches, and you pass certain actions or properties that you want to assert. So I know we have been talking about theory, but it always makes sense to take a look at the application. So, so let's understand the application first. And I think it would be better if I just show you in code. So let's take a look at the application. So I've launched the basic sample application, you will find the code for it in the testing samples. If you're opening it for the first time, just open the build.gradle file in Android Studio, and you'll come to a screen like this. Here in the build.gradle as you can. So if I search for Espresso, you can see I have the Espresso core already mentioned here. And and we have some additional dependencies. Of course, feel free to use the same structure. We have like specified the versions of these libraries in just build.gradle. So we are using Espresso version 3.5. And we also have the instrumentation specified. Yeah, we can see that within Android under default config, we have the test instrumentation runner specified. So perfect. Let's run this application and understand the flow that we want to automate. So I'll just run this app directly. And I have an emulator pre created. But if you are not familiar with it, the tutorial is fairly simple. You can go to emulator and create a new one. If anyone has any problems, just let me know. I can like discuss about it in the end as well. So here you have a simple view at hand or a single activity. So this activity has a simple edit text. And if I let's say type something here, let's say I say Selenium Con when I click on change text, you can see the text changes in this text view. One other flow is you can type the text you can click on open activity and it will open a new activity with the text that we just typed. So what we want to automate is I want to launch this particular screen on the application. I want to type some text and click on this button and then see that the text changes to what I'm expecting, right? So let's see a test for just that. But before we do it, we want to also understand a bit about the test structure. So let's see that quickly. So this we just described the flow that we want to verify. You want to make sure that you are able to launch the screen you want to test, right? And for that, we use a J unit rule. And we specify the actual class of the activity that we want to launch. So in this case, it's main activity. And I'll show you how we figured out that this is the activity as well. But for now, just understand the syntax. So you specify an activity scenario rule, and you specify the name of the class that you want to launch. So I've created a variable with activity scenario rule, I've created a new instance of it, and I've passed main activity dot class, right? So yeah, these are the three main important things. As you test more activities, you will have to change these. Next, of course, we want to find the element. So this syntax should now start to look a bit familiar, you use with ID, and we try to find the text box. Next, we want to type some text. So we use the type text method, and we give it some text that we wanted to enter on that. And once it's done, we want to also close the keyboard. So here you can see that we can give multiple actions in the perform method, which is great. So you can change some actions together. And lastly, we want to check that, Hey, is it matching the text that I'm expecting? So we use check matches, and we use the width text method and specify that string that we are expecting. So let's see this in our actual test, I'll just collapse this emulator. And let me show you the actual test. So if you see the test, this is how it looks like. These are all the dependencies. Don't worry, we will understand what they are in in a while. But you start with writing, of course, a class, and you annotate it with Android J unit four dot class. We use the run with annotation to let Android know that hey, this is a test class that we want to use. Next, as I showed you, we use the J unit rule, which creates an activity scenario rule with the main activity. So one way of finding the activity is of course to take a look at the app source code. So you can see basic sample main activity. And this could give you a hint that okay, this is one activity that we are looking at. If you are an Android developer, this is all very clear to you. So now how does my test look like? So of course, I annotate it with add test to indicate that this is something I can run. And then I specify on view, right? So within on view, we have with ID, R dot ID, edit text user input. Naturally, the next question is how do I figure out this ID, right? So luckily, Android Studio has a layout inspector, you can open it with going to tools, layout inspector, and it should bring up an inspector similar to most of the other element inspectors, like Appium has it as well. So as you can see, it launches my application, which is already running in the emulator, you can specify which specific activity you want to basically inspect, or you can stop the inspector, it has a bunch of other controls for you to look at. But the most important is you can see your actual application, you can see the different elements if you hover over it. So let's say I want to see, okay, what is this text? What is this edit text look like? So I can see like everything is under a linear layout. I have a text view as a label. I have a text box where I can enter some text. I have a change text button and an activity change text button. You can see like the ID of these elements is mentioned here. And you can also scroll a bit further and see some more attributes like this is the actual ID. What is the text for this element? Then what are its layout properties? What are its active accessibility properties? Is it clickable? Is it visible and stuff? So if you are writing a test and you want to check a specific aspect of it, you can very easily find the property and use the layout inspector to understand it. This is just great. So now in our case, we wanted to actually write something in this text box, click on it and check the label, right? So we can find the IDs of it from here. Let me just collapse this. You can even just use the autocomplete and find the element, right? This is great. You don't need to do any additional activity to find your elements. Next, we want to perform some action on it. So of course, we use type text and you can click on type text and you can see that these are all methods of view actions dot Java. So in case you want to understand what other methods you have, you can you, we can open structure and you can see all the different actions or the view actions that espresso has available for it. And any action that you take a look at has good documentation. So you can just read through it and try to use it. If this is also not clear, espresso docs are pretty self-explanatory for us to understand. I stored the text that I want to enter as a constant here. And I also instruct that I want to close the keyboard once I'm done typing to make sure that no other elements are overlapping. This is usually a good practice. Finally, once I perform this action, I want to click on the button. So again, I start with on view with ID, specify change text button and then click, right? And naturally once I'm done with this, I want to of course verify that the text changed. So again, I start with on view. I specify with ID with the labels ID. And then I call the check method on it and check that hey, it should match the text that I'm looking for. So you can see I use matches. Within matches, I can specify either one or multiple assertions. So I can go to with text. And you can see this is view matchers class, which has a bunch of matchers already defined for us. In case you want to specify a custom matcher for your use cases, expressway API is flexible and you can do that as well. So this is great. Let's just run the test and see if it works. I'll just run this. So it opens our app, types the text and closes. You can see the entire test executed just within two seconds, which is wonderful. Um, so if you remember, I also showed you another flow in this application wherein you can enter some text and click on the second button and it opens a different activity. I have a test for that as well. So for the most part, the first part remains same, you enter some text, but you click on a different button. And then you want to check that the text is present on the different activity. In this case, if you have launched a new activity, you don't need to tell Espresso what that new activity is. It will be able to find it on the screen. So you just specify, okay, I want to find the show text view element and I want to check that the text is updated based on what I said. So this is great. Hooray, we have written our first Espresso test. Congratulations. This gives you an idea of how to write a basic Espresso test. And we are of course going to build more on it. All right. Okay, so I hope that introduction section sort of made sense and you get an idea of what a basic test looks like. I have a quiz for you. So if you would please humor me and try to answer that. I'll just post the link to it in the chat. Just give me a moment. Okay, and probably let's do a timer so that we are on time, maybe two minutes. So a moment, I'll just share my browser. Okay, last 15 seconds, you can also take it down. So if you've already taken the quiz, I will see the results in a moment. Let's continue. So now it's time that we understand how we can automate list like controls with Espresso. So using Espresso, we can perform a scroll type of action on a list. We need this because in most modern Android applications, you will have the same component being repeated in a list. And we would want to let's say scroll in that list to perform action on a specific element. In case of Android, we generally have two types of list. One is called as a recycler viewer, wherein we have a small number of child elements that are created. And then the same elements are recycled as you scroll. For these type of use cases, we can use the on view control with recycler view actions. We also have another type of list called as an adapter viewer, wherein the data in the list is backed by an adapter. And in such cases, we don't use on view. Instead, we use on data with a custom matcher based on how the adapter itself is representing the data. For these type of methods, scroll to does not work since the view is created dynamically and it needs an existing view. Don't worry, we will be seeing examples of both of these in just a short while. Let's take a look at adapter view first. So here is a simple application under test, we will use the data adapter sample from our testing samples repository. As you can see, in this application, I have a list view component, wherein every row has a text view with a label like item 68 69 and so on and has a toggle button to the right. When the user clicks on any element in this list, we have a label up top called as clicked on a row that is updated. So how do we write a test for this? As we saw earlier, we start with writing our class annotated with Android J unit four. We then launch the activity. In this case, it's a long list activity and I'll show you this in the app in just a minute. But for now, I'm trying to make you understand the common patterns we have for writing an espresso test. So we create our activity scenario rule and specify long list activity. Before we actually write our test, it makes sense to do a negative test first. So we will see, hey, does this view that we are interested in, does it even exist? So we start with trying to find an element, whether it's present on the screen, we'll use the with text view matcher. And then we'll check that it does not exist in our assertion. Next, we want to try to scroll to our item. Since this is an adapter view, as I mentioned, we will use on data. Also, notice within the on data, I'm making use of a has entry matcher. A has entry matcher is able to find a given entry in a key value sort of data structure, something like a hash map. And in this particular example, the actual adapter viewer is backed by a hash map having key as row text and value as the actual text. We'll see this in a minute. But what I'm trying to tell espresso is, hey, espresso, can you find me a row element wherein the key is equal to long list activity dot row text, and the value has item 99. And finally, once I have that element, I of course try to make sure that this is displayed on the screen. Don't worry, espresso is going to take care of actually scrolling to that, but make note of we use is completely displayed as an assertion here. What if I want to click on an element in a list? Well, you can simply use on child view. And give it, of course, the locator we are interested in, in this case, it's a row content text view. And finally, we just perform a click action on it. Once we perform a click, as I mentioned, a label gets updated. So we can just verify it with a straightforward on view, giving the ID of selection row view and then trying to match match it with the given text. And that's about it for the adapter view. Now let's take a live look at the example so that we understand the test a bit better. So let me bring up Android Studio and I'm going to launch data adapter sample. I'm going to fast forward the Gradle sync, just to save a bit of time. Okay, so our project is completely loaded. Let's just take a look at the app under test very quickly. Okay, so our application is booted. And as I showed you, we have a list. Let's just show you the layout very quickly with layout inspector. So as I mentioned, we have a list view at hand, which is inside a linear layout and we have multiple row items. As you can see, this has many items, but at a time we are only loading certain of them. Every row has a text view, which is a label and a button next to it. I can scroll in this. And as I scroll, you can see the value of these changes. If I click on one, you can see that this label is updated. Now, what if I want to do the same thing with an espresso test? So let's take a look at that very quickly. Before we begin there, I'll just show you the long list activity. And let me just collapse the emulator show you the structure. So as I mentioned, we have our on create, which is tasked with basically using an adapter and filling this list with certain data. But this is the important part. As you can see, I have a make item method, which is visible for testing. This is a useful construct so that I can make use of it from espresso tests. I have a hash map. And every hash map has a key called as row text, wherein I'm generating these label values. And then I have a row enabled value, mapping to it. And this is the actual adapter that is backing this particular list, you can see that there is a long list adapter that extends simple adapter and then basically has code to populate this. It's okay. If you don't understand all the details here, mostly we are going to be interested in writing tests. So let's just take a look at that quickly. And so this is for long list activity test. Alright, so we start our test, the usual business as I described, we launch our long list activity here. We have our negative test to make sure that when we first launch the application the item 99 is not visible. And then we have another test that checks for the scrolling part. So as you can see, I have an on row method. And I'm given it last item ID. If you go to last item ID, that is basically the item 99. You might be wondering what this on row method is all about. Since we have to repeat the same on data expression and again and again, so we I just refactored it into a simple method, which takes a row text and has the same logic that I described earlier with on data has entry and checking whether that string is present in the hash map or not. And it returns a data interaction at the end of the day. So I can just go to my first test. And as you can see using this I'm able to scroll and then check that this is completely displayed. And that's about it. Pretty simple, right? So you can use on data to scroll in an adapter viewer and just go ahead with your tests. Now that we have understood what adapter viewer is, let's take a look at recycler viewer. As I mentioned, it's a different type of list which recycles the same elements again. However, we don't need to use on data in this case. To basically work with the recycler viewer, we need to add an additional package called as espresso hyphen contrip. And you can see this in the example that we'll see in just a short while. So when it comes to scrolling, you have multiple methods at hand, you have scroll to scroll to a holder or a specific position. Similarly, if you want to perform an action, you have action on item, if you want to perform an action on the holder item, then you can use that or if you want to just perform an action at a given position, we have an option for that as well. Let's take a look at the simple application. So I have a basic recycler viewer sample which has just a list of elements. And as you can see in the screenshot, we have a frame layout as a child of this recycler viewer and each of them has a simple text view with a text like this is an element number and we dynamically generate more numbers. So what if we wanted to automate this? So this is how a simple test looks like wherein we are trying to see whether a given element is not present in the list. So let's understand this in a bit more detail. So we want to perform a scroll action. So we make use of recycler view actions and the scroll to method. And then we check whether this particular recycler view has a descendant with a specific text or not. In this case, we are giving a text which is definitely not going to be present. So this test should fail. Of course, since this test fails, we will annotate this test with expected perform exception dot class to make sure that this is an actual negative test that doesn't that fails for no reason and raises a false alarm. Now, since we want to scroll to a fixed position and perform an action, we will use a similar syntax, wherein we will use recycler view actions. And we'll say, Hey, we want to perform an action at a given item, which is there at a specific position. The first argument is an actual item that we want to perform an action on. And the second is the actual action, which is click in this particular case. Once we do the click, we just verify whether the label up top is updated with an expected value. So hey, we say this is the element and we expect a specific number to be present that we clicked on. And then we just use a simple on view with text to find that specific element, and then check that it is displayed. So let's just take a look at this example quickly. So for this, we are going to launch the recycler view sample. And I'll let Gradle quickly sync and build this application. This is the main benefit of a watch party, right? I get to play God and I can just skip and fast forward through the boring parts so that you can just see the interesting parts. Alright, so let's launch our application under test. And as you can see, this is our sample application, I can keep on scrolling. Notice there is a specific position in the middle that says this is the middle. This is interesting, we have a test for this. But as you scroll within this list, Android is going to recycle the components in a much more effective manner. We have the main activity here, which has all the logic to configure this. Now let's take a look at our test. So again, to start with, we annotate our class with J unit four. And this is the first test that I just described in a while, wherein we try to find the recycler view with on view. And then we try to perform recycler view action, trying to scroll to a descendant, which is definitely not going to be present. And I annotated with this expected exception. I can try to run this test. And the test passed, as you can see, it only took a second to launch the application and perform this simple test. Next, we actually want to try to scroll to the expect expected element. So we have the on view where when we find the recycler view, we use recycler view actions and try to perform an action. So here I'm trying to say I want to take a look at the 40th element. And I pass that I also say that I want to click on it. And once I have clicked on it, I want to make sure that the text at top matches. So let me just run this test quickly. And it runs again. Now, I notice I mentioned the specific text. This is the middle in the between. Let's say I want to actually verify that recycler view has this specific element. For that, we use the scroll to holder. And I want to make sure that I'm able to basically find this element. So I give a custom matcher which says, hey, can you find me an element which is in the middle? If you take a look at this custom matcher, we have our own type safe matcher, which has the type custom adapter dot view holder. This provides an implementation of our own matcher wherein we say this specific matcher should have this text. And finally, we have the override the matches safety method, which takes a view holder as an argument, and then calls the get is in the middle method. You might be wondering where this method actually lies. This method is something that we need to implement in the application under test. So this is the actual part where a developer or you is going to go in and modify the view holder a bit, just to make sure that you add some support for testing, wherein in this case, it's like we use a Boolean field to try to see, hey, if if I have a row or a text view with a certain text, then set this Boolean to true. And the same Boolean is something that I verify in outside. So this is just a small example of how you can build some test ability into your app and how espresso facilitates these type of use cases. They could obviously work for more complex use cases as well. And with that, you now know how to work with list controls, which are very common with Android components. All right, let's get probably it's time for quiz number two. So let me just post the link in the chat. And let me start the timer. Okay. Have at it. I could I think listen to this music all day long. I hope that quiz was fun. Let's move on to the next section. Take a look at how to automate intents. You might be wondering what intents is. Intents can be thought of as a data structure that holds a description of an action to be performed. It's used to pass data around between activities a lot. And this is one of the major use cases. Let's see how to work with it with espresso. So this is a sample application. Let's understand the application first. I have an intense basic sample where in I have a text box, a call button and a pick number. If I choose pick number is going to generate a random valid phone number. And when I tap on the call number button, it's going to launch a dialer screen, which is a different screen or activity within Android. Now behind the wraps, our application fires an intent to essentially launch this dialer screen. And let's say we want to validate that our application has successfully launched the dialer activity. In case we want to validate that the activity actually launched, we will use intending. And let me show you an example with some code. Before we begin to work with intents, we need to add espresso hyphen intents dependency to our apps build or gradle. Also note that this is only compatible with espresso 2.1 plus an Android testing library version 0.3 plus. So we need to make sure that the version of those dependencies is also updated. Once done, as we have been seeing, we launch our activity using activity scenario rule. In this case, it's dialer activity. There are couple of key setups and tear downs we need to do to make intents work. So we write a method called as setup intents annotated with add before and call the init method inside. What this would do is it will initialize our intents and begin recording. And this would ensure that whenever our application actually calls that intent, we have a way of verifying it. Finally, once we are done with our test, we need to clear down any state that we created. So we call the release method inside a tear down intents method and annotated with add after so that after every test, this particular block gets executed. To work with our test, we need to grant it the call phone permission, which is in this case, we can just use grant permission rule called the grant method on top and just pass it the permission that we actually need. We annotate it with add rule so that J unit automatically calls this for us. So now coming to our test, this is a plain simple example that we have been seeing, we find a text, we find an edit text using its ID, and we type a valid phone number, close the keyboard. Once we are done, we tap on a call button using ID. So now assuming that the user tapped on the call number button, we want to verify whether our intent was actually called, right? So for that, we use the intended method. Within intended, we use the all of matcher that basically makes sure that all the required action and data has been passed to the required intent. And intent can usually be thought of as a sort of key value pair, wherein you have actions specifying different actions like in this case basically launching a dialer activity, or it could be other actions, system actions within Android and whatnot, and has data basically has some representation of data that we want to pass across activities. In this case, it's a simple phone number. And we'll see that in our test in just a moment. To make sure that both the assertions happen, we wrap it with an all of matcher, which is going to only pass if both the conditions evaluate to true. All right. So before we move on, let's take a look at an actual test. For this example, we'll use the intense basic sample from our testing samples repository. And you can take a look at the build.gradle. We use the standard dependency versions. And as I mentioned, we have espresso intents already defined for test implementation, so that it's available in J unit. In terms of the activity, we have a simple dialer activity. And when I mentioned the structure for an actual intent, here, you can see that we have an actual call to create a new intent with the type as action call. And the actual value in this intent is essentially a phone number. So we have the uri.parse, we give a telephone prefix, and then we give an actual number. Here, the number is actually the text that you set. Once this intent is called, if the request code is matching and the result is also valid, then we set the appropriate values in our field. Let's take a look at our test. So as I mentioned, we create a test class, we create a dummy phone number that we want to enter. We also grant the call permission. And we set up to launch our dialer activity before the test initializes. Here you can see the add before method with the intent method being called, and the release method called in a method annotated with add after. So this is our actual test. So assuming we want to perform the act of entering a number, tapping on call number and verifying that the intent validates, it has the exact same steps that I called out. So let's just run this test and see if it works. So as you can see, we enter the phone number, tap on call number. And as you can see, the dialer activity gets launched and our test passes. Great. Let's just cancel this activity now. So in the previous test, we saw that an espresso intent could launch another activity and we can quickly validate them using the intended method. However, if we only care about the logic of our application and not so much about a third party application, in this case, a dialer application, or a contacts application, which is let's say managed by Google or some other OEM, then we can actually just verify that our application made the desired call and actually stub out any call to this third party application. So let's see an example of how this is achieved with espresso. So how do you set up a stub, right? Here, we start with intending method. And then within intending, we add a condition to check whether this is an internal call or it's not an internal call. In this case, we want to set a stub for our dialer activity, which is not an internal call. So we give that as the condition, and we specify the behavior that we expect in this case. So whenever this happens, we want our stub to return some canned response, right? And in this case, we just return a new activity result from the instrumentation class, and we return the result code as result okay, with a null data type. So this is how you set up your stub. Couple of other use cases might be you might want to just stub out any calls to a particular component that has a specific class name. In this case, let's say you want to stub out all the calls to contact activity, you can just specify that you start with a dot followed by the class name. Let's say you want to stub out all calls to a particular package, you can also use the two package matcher there, and you can just specify the package path. So let's take a look at the example and see this in action. So in the previous example, as you saw, we have the same code here, but let's say we want to set up our stub, right? I'll just uncomment this bit of code, wherein we are setting the stub that I just showed you earlier. If you are interested in what is internal is, you can see it is an intent matcher provided by espresso that matches whether the package is the same as the target package. In this case, we inverse it since we want all external intents to be stubbed, and give the same canned response. So now let's just run the test. And if this works, fine, our dialer activity should actually not get launched, and our test should pass. So we enter the number, tap on call number, and that's it. No dialer activity launched, the test also executed faster. So this is how you work with intents using espresso. Now let's take a look at what Okay, so we have gone through almost like 60% of the presentation. Hopefully you are ready for the next quiz. Let me share the thing here. Let's start the timer. I guess the times let's move on to the next section. idling resources is all about espresso is a pretty smart framework, and it automatically takes care of common synchronization use cases for us. Thus, ensuring that the test authors don't have to put too much synchronization in place. When we invoke on view method in espresso, espresso is smart enough to automatically do a bunch of checks. It checks whether the message queue is empty. Are there any instances of facing tasks that are executing any tasks in the background? And are all developer defined idling resources actually idle? This leads to much more robust tests, because espresso has an insight into the state of the application. And thus, chances are the tests are going to be less flaky. However, there is a caveat to this. Espresso is not aware of all types of operations that an Android app can do. For instance, it's not aware of any async operations that are handled by a background thread. For such cases, we need to register them as idling resources. You may be wondering, do we really need idling resources? Can't we just do a simple thread dot sleep or something like that? Well, you certainly can, but it's not a very good practice. And there are certain reasons for it. For instance, you might say that I can introduce a delay in my application with just thread dot sleep. However, this is not a very good idea because you won't often know how much time your operations will take when it's run on slower devices, or devices on slower network conditions. In such cases, this approach scales very poorly, because the time taken by an operation can change dynamically. And this is a very common cause of flaky tests. So you should try to avoid it. The next thing is you might think I can just use some retry wrappers and keep on retrying in a loop until my async operations are completed. And while many frameworks take this approach, it's again not very deterministic and actually can vary due to network and other device conditions. There is also a solution using countdown latch, which can wait for some operations executing on one thread to be complete before it can actually proceed. The objects generally have a timeout associated. However, there is a maintenance overhead with managing this complexity in your code. In case you are really interested about the pros and cons, I would encourage you to read the Android developer guide, which has a lot more context. So when should you actually use idling resources? Well, at any point in your application where something happens and you have to validate that on the UI, then it is a good idea to register it as an idling resource. Some common use cases are you're loading something from the internet or you're loading some data from local DB. In case you are dealing with connections with databases or callbacks, or if you are managing any services, using system or intent service, or you are doing bitmap transformations and using some complex business logic, all these are good use cases for us to implement idling resources. So I hope by now it gives you a good idea that idling resource is an important feature that Espresso gives that allows you to synchronize your code in all these conditions. Let's understand how to set it up. Espresso provides a bunch of utilities in the Espresso idling resource package. So make sure you add it in your apps build.gradle. Let's take a look at the simple application, we'll be using basic idling resource sample, wherein we have a text box. And once you tap on the button, we actually put this on a background thread. So it will take some time for this message to actually show up. And this is a very good example since this task is happening in the background. And this is something Espresso doesn't handle out of the box. So this is a simple Gherkin scenario, we type some text, we tap on the button, and then we expect that text to be changed with a delay. And here is a simple test for this, it mostly builds on top of what we have already seen. So you essentially type some text, close the keyboard, click on a button and again assert that the expected test is present. So what do you think will happen if I just run this scenario out of the box? If you guessed it will fail you guessed correctly, because we are actually going to get an espresso error, wherein it expected a certain text to be present, but it actually got another text. So in this case, we were expecting this is gonna take some time, but instead, the text was waiting for message, while there was a delay on the background thread in this case. So let's understand how to work with idling resources. You need to add a private variable of type idling resource. Next, you basically launch your activity. This is another way for you to launch an activity. Here we use activity scenario class, and then we use the launch method on it, and provide it the class that you wanted to load. In this case, it's main activity dot class. Next, we need to register our resource into something called as an idling registry. If you don't understand what it means, just understand that it has code or logic to handle registering and unregistering of idling resources from your application code. And these resources are obviously used by espresso to provide synchronization. Any registered resources in idling registry are automatically synchronized against each espresso interaction. So let's understand how we implement this in code. To start with, we basically create a lambda. In this case, we create an activity action and give it the type main activity. Let's call this as activate and then define the next steps. We then get the idling resource from the activity. In case you are wondering where the implementation of this is, it is actually present in the app source code and I will show you in the example in just a while. Finally, once you get the idling resource, we get an instance of idling registry and then we register this idling resource into it using the register method. And the entire lambda is called within activity scenarios on activity lifecycle method. Wonderful. So now we want to make sure that this registration happens before the test executes. So we put it into an add before method. Also, we need to make sure that the idling resource is visible for testing. So we annotate it in the app source code. Here I have a simple method called as get idling resource which checks if the idling resource is null and if it is, then it returns an instance of simple idling resource. I'll show you this basic class when we go through the code example. Finally, after the test executes, we need to unregister the idling resource from the idling registry. So we check for whether the instance is not null and if it is not, then we call the unregister method and annotate it with add after. While the add before and add after definitely works, it's also possible to implement a junit rule and I would leave that as an exercise to you. I'll have a link for you in the references that you can see to implement this for yourself. Now the implementation that I talked about is just a basic implementation. There are other types of idling resource implementations. For example, counting idling resource, URI idling resource, idling thread pool executor, schedule thread pool executor. There are multiple community developed idling resource implementations like Rx idler from square for Rx Java and and much more. So you can read the official guide and also Google around for multiple idling resource implementations that the community has built. Now let's take a look at the code example before we move on to the next section. So for this example, we'll use idling resource sample from our testing samples repository. All right, so let's take a look at build.gradle. As you can see, we have the espresso idling resource added here. Also a small tip when you're launching these projects, sometimes you might get some error around android gradle plugin. At that point of time, just take a look at what version of android studio you have and what is the android gradle plugin for that and just update it appropriately. I'm using android bumblebee. So 7.1.0 is the compatible version. Let me run the app and show you the application quickly. So here we have the simple application. I can type something here and tap on change text taking time. And as you can see, for some time I see this message and after that I get the same text I typed in this text box. How does this work in the code? Let me just show you very quickly. So we have the main activity here and as you can see we have a simple idling resource defined inside. If you go to simple idling resource, you can see it implements the idling resource interface and for this simple implementation it uses a flag to determine whether this resource is idle or not. At any point of time you can get the status for it and also you can set the idle state. Also to stimulate the delay, we have a delayer class here which specifically has the code to introduce an artificial delay in our application. As you can see, it basically creates a handler and within the handler it puts the task of setting our text into a background thread. Also, as you can see the idling resource that we just defined has to be annotated with visible for testing so that we can use it in our espresso tests. In most cases there might be an implementation of idling resource already existing so feel free to use that. For this example, we are just going to take a look and understand the structure so that in case you have to implement one for yourself, it's very clear. Now let's take a look at our actual test. So as we saw earlier in the slides, we create an instance of idling resource. We register our idling resource by first launching the activity and then creating our lambda of activity action getting the idling resource. So if you go here, you can see this is the same method I showed you and that we implemented in our apps main activity and opened it up for testing. Finally, we register it into idling registry. After the test, we also unregister it and this is the simple test that we have. Let me show you how espresso behaves if there is no idling resource registered. So I'll just make sure I comment the part where we registered the idling resource into the registry and also the part where we unregister it and let's run the test. So as you can see, we launched our application and the test failed as expected. As you can see, it expected an instance of text view where the text should be this is going to take some time, but instead it actually was waiting for message. And this was because this task was happening on a background thread that espresso was not aware of. Now let's fix this with idling resource. So we'll add our idling resource again into the activity and also uncomment the tear down part. And let's just run the test again. So you enter the text, tap on the button and as you can see the test passed. So this is the power of idling resource. Implement it and make your tests more stable and let go of those flaky tests that fail because your application did not know any better. Switching gears to a different... Okay, I hope you are ready for the quiz and I'm sorry. I think this session is long drawn out. You might be feeling tired, but bear with me. The next section is very interesting for people with Selenium experience. So here's the quiz. Let me just share the browser and start the timer. So I hope everyone is done. Let's move on to the final section of the presentation. Let's understand how to automate reviews. The next topic now. Many Android apps these days will expose certain business logic in web views within native apps. You can think of it as a small mobile browser like Chrome or Firefox that is able to render web pages but on your phone's form factor. It is quite important from a testing perspective to be able to cover the interactions of your native app with these web views as there could be some regressions that you might miss if this is not covered. Some of the examples where a mobile app might have web views are there might be help or support pages or marketing content or terms and conditions that needs to be updated quite frequently and should not need an actual app release through the Play Store to go through. One of the advantages of content over web views is that it can be very easily updated by your business teams without much overhead. Now Espresso provides a library called as Espresso Web that provides an Espresso-like API interface over the Selenium WebDriver API. So before we understand how to write a web test let's understand when you should actually write the web test. So if you want to cover the user journeys between your native app and web views and you want to test the interaction then you are in the right place and you should write an Espresso web test. However if your intent is to actually verify the web views content or functionality without any interaction from the native app then you would be much better served to write a web driver or an equivalent test in another framework. The main reason for such an approach is writing a web test outside of Espresso would run much faster in case you only care about that assertion. So how does this work behind the raps? Essentially Espresso Web exposes a javascript bridge that allows Espresso to interact with the web driver framework. The main key component here is called as Atoms and you can think of it as something similar to the view matcher and view action classes that we have been dealing with. So Espresso Web basically wraps these atoms with web and web.web interaction classes. If you are familiar with a Selenium or Equivalent framework then you can just use find element or get element methods and use the familiar locators like ID, Xpath, CSS and class name etc. So before we begin we naturally start by adding Espresso Web dependency to our Android test implementation. Now let's understand the application under test. For this we will be using the basic Espresso Web sample from our testing samples repository. Here on the left you can see a simple web view wherein you have a label and you have a text box and when you enter a text here you have two options you can either tap on change text that will update the label up top or you can click on change text and submit which is going to update the content in another web page. Let's say we want to test whether the web view inside the native app works and the scenario is basically enter some text tap on change text button and expect that the label's text is updated. This is pretty similar to the basic examples we've been seeing. The only difference is now we have to work inside a web view. So before we begin how do you actually inspect your application? If you try to use the layout inspector from Android Studio you will find that it won't be able to give you any detail about the app's structure. Rather for this we use Chrome developer tools. So to basically work with it make sure you connect your emulator or device via USB ensure that USB debugging is enabled. You can enable it by going to the build number in your phone's settings and then keep on tapping on the build number until developer options is enabled. And finally you can just type chrome colon double forward slash inspect and you'll get a screen like this in your Chrome browser. Just click on the inspect button and it will open up a familiar Chrome developer tools that you might have used while automating Selenium tests. So you'll see a Chrome developer tool like this and this should appear very familiar to Selenium users. You have on the left a representation of the web page and on the right you have elements wherein you can see the XML DOM structure and with this you'll be able to find the locator you're looking for. So now let's move on to actually writing our test. Before you can write your test you need to make sure that your application supports Chrome debugging. For this you need to add some snippets into your app's source code and we'll see this code in detail while looking at the actual test in Android studio. But for now just remember you need to add set web contents debugging enabled and set the build config as debug so that it's only works for your debug applications and not production. And you also need to set the mobile web views settings to enable JavaScript as you can see on this. So before beginning to write your web test we start with a familiar activity scenario rule. Give the name of the activity that has the web view. In this case it's a webview activity.class. Next before you can actually start writing your web test you need to enable JavaScript on this web view. So for this case we use on web view method and we use force JavaScript enabled. If your application has a single web view then you don't need to even give the ID. But if there were multiple web views you would need to find it using the with ID matcher. Great. So now that your before method is set up to enable JavaScript execution this is how you start your web test. You first find the view on which you want to perform some action. So here we use on web view instead of on view. And the with ID looks almost identical to an espresso test. Now the on web view method is going to return an object of web interaction which will expose web api actions and help us drive our web view. It should come as no surprise that espresso web supports all the locators that you are used to as a selenium user and so you can use any of these locators while trying to find your elements. Next we want to find our element so we use with element method and then within it we pass find element which accepts two parameters. The first is an actual locator type in this case we'll use ID and then the second is the actual value of that locator. In this case the ID of the text box is text input. We want to make sure that we clear the text before we type something. So we call the perform method on top of this and just call the clear element method inside. And finally once any text is cleared we then call the web keys method and then pass it the text that we want espresso to type. Finally we can again find our button so we use with element and the same find element method and this time again we use the ID submit btn which we get from chrome dev tools. And lastly we perform a web click so we call perform and web click method on it. So after we tap on this button we expect the label to be updated right. So we find the label using the same with element and find element methods. And lastly once we have a handle to this label we we call the check method and within it we pass a web matches that accepts two parameters. The first one actually gets the text from the label using using get text method and the second we check that the value that we get actually contains the string that we typed using contains string. Again you would be very easily able to go and see how these method definition looks like and use the specific methods for your use case. Now let's fire up Android Studio and actually see this in action. So we go to our testing samples and under espresso web basic sample open our project. Okay now that the build is done let's just show you the application under test. So here you can see the application under test. I can type some text click on change text and again click on this that basically opens the text in a new web page. Let's take a look at the app source code. So if we go to webview activity let me collapse the emulator for a moment. You can see that I've added the set web contents debugging enabled. We have also set JavaScript to be enabled and there is a bunch of code to make sure that we are able to launch our web view such as being able to get the intent URL load this particular URL and we initialize our web view client in the web view. Since set web contents debugging requires KitKat version plus thus we add the requires API annotation and say it needs to be a version greater than or equal to KitKat. Now let's take a look at our test. So here we start with our web view test. We initialize the activity scenario rule with web view activity that we just saw. We create a add before method so that for every web view we force the JavaScript to be enabled and these are the same steps that I described. So here you can see we have the on web view with ID and then we use the with element and find element methods to find our respective elements. We can also go to locator class and then see that it supports all the selenium locators. We use clear element web keys to type something finally finding the button click on it and then check that the response label has the expected text using web matches and contains string. So this is our first test. If you remember there was another test wherein we click on the change button and submit and it opened it in a new web page. I have the same test automated here as well. If you can notice it's almost identical except for the button that we actually click. When the web page changes we don't need to provide additional context to espresso about the new web view. It will be able to find on its own. We just specify the actual element where we want to perform this assertion. Let me just run both these tests and that's it. Both the tests executed within three seconds. Quite fast, right? All right. So with this we come to an end to our talk. Here are all the resources that I've referenced while creating this talk. So you can find the five part blog series on my blog automation hacks.io and I've also given a link to them. I would also recommend you to go through Android developer espresso pages. They are very informative and covers some more additional information. I've given you some helpful hyperlinks to directly explore the content. So with this we come to an end to this talk. I had a lot of fun putting these slides up and going through this with you and I hope you also learned something today. Now if there are any questions I'll be more than happy to take them now or feel free to reach out to me over LinkedIn and Twitter and we can discuss on this offline as well. So I think we are right on time. We didn't have time for the quiz. I posted a link. You can also take the quiz afterwards and ping me. I'll post some statistics about how they went. In case there are any questions, maybe we can take them now or maybe go to the hang over statement.