 And, well, you might be wondering, who's that blue guy? That's me. And you might also be wondering, how will this story go? Well, that's what I'm going to tell you. Because this story, I'm going to tell you about how React Native, Appium, and myself made each other shine. But before I'm going to dive into deep, I'm going to show you some stuff about what we're going to walk through. First of all, we're going to talk a little bit about the app. Currently, I'm working for Tele2. Tele2 is a telecom company within Netherlands, and they're now building a new React Native app. They're trying to do it a little bit different than the standard apps, standard mobile apps. They wanted to use a conversational UI. And a conversational UI is where you not only can use the menu to reach your data, use it, that kind of stuff, but you can use a chatbot to ask him questions, and he will find everything for you. If you want to use the app, the first thing you need to do is kind of like buying a ticket. You need to do your onboarding process. And how that part will work, I'm going to show you in a demo of the app. Looks like the clicker is not working all the time. And basically what you're seeing here, I hope it's quite clear for you. This is the first step in our app. We need to do an onboarding process, and kind of like with a conversational UI, as they're saying it themselves, kind of like talking with the customer. And they hope that the customer will log in, fill in his credentials. And then he will get all kinds of message, like you're doing a good job. Do you want to secure your app with a PIN code? You fill it in. You need to accept all the conditions, the terms and the conditions. And then you're done. Each time you're then logging in, you will see this screen. How does it go? You're able to, for example, what I'm doing here is, what's my name? I'm asking it to the chatbot. Chatbot is coming back and is saying, well, you're with him. That's nice. I can do a lot more. I can ask him what my data usage is, and it will show all the data to me. So this is kind of like how the app works. Hopefully I'm not going too fast. When I started at Tella 2, it was in November 2017. I already did some investigation about how should I automate the app. I've came on to a framework based on Appium. I'm using Appium Desktop also to inspect my app. I'm using WebDriver.io, kind of like my Augustrator. I'm using Cucumber for the behavior-driven development that the customer wants. And I'm using a very nice reporter. You should check it out. It's mine, multiple Cucumber HTML reporter to visualize all the steps and give you a good result. The investigation that I did, I gave a presentation about it in London in April. So if you want to see how I did my investigation, you can also view it also in YouTube. But when I started the investigation, the only thing I had was my local machine. I had the app. And I had a simulator and an emulator, iOS and Android. And that was the only thing I had because Tella 2 was currently, or was investigating if they could buy a contract for a cloud provider. And so I didn't need to think about parallel execution. I only had one device that was enough for me. That was the basics for me to set up the framework. When I started with it, one of the first steps I needed to do, one of the basic requirements was I needed to have a cross-platform solution because I don't want to make a script or two scripts to use for an Android and for iOS. Because both apps with React Native, in our case, were the same. So I've chosen a hybrid solution as I call it itself. I'm using accessibility labels, and I will dive into it later. And I'm using Xpath. And you might be wondering why 2% could be 5%, but it's that low because I can find everything with accessibility labels. I only need the Xpath selectors when I'm using, if I want to retrieve text, for example, when you're doing retrieving text on an iOS element, you will get a complete string, including its children. When you do it on Android, you need to do something more. So if we dive into the solution, I don't know how many people know React Native, but it's kind of like just using JavaScript, building a complete new app. And what I did to get the accessibility labels on the devices or in on the apps, I created a specific method. It's called test properties. What you're seeing here, it returns a accessibility label. But I put the arrow a little bit too low. What you also see here is, is it an automation build? I was able to create specific builds. We have a beta build. We have a release build. But we also have an automation build. So only when I'm having an automation build, I'm returning the accessibility labels I need in my specific automation build. When I put this into the code, for example, I have here a piece of code of a select box, select menu box. I didn't implement the complete code. But what you're seeing here, you have a view element. And the only thing I'm doing here is adding the test properties to it. And then when the application has been built, it has the accessibility labels on it. If you then look at the implementation, and this is, for example, the select menu, I had one issue on iOS. I got five elements back. And I was not able to interact with it. So I needed to think about a way to only get one element back. Otherwise, I would have failures. So, the advantage of my method is I only need to adjust it in one place. I said, well, when I'm an automation build, and when I'm iOS, I could use test study. Test study is one of the properties you can use on specific elements within React Native. But in the end, it will compile to an accessibility label. And when I've implemented this part, you eventually will see in iOS that I only got one label back, one element back. And now I was able to interact with this element in a very easy way. This is basically the setup for all the selectors. So, in my case, the first step of the framework was done. But then, when I started with the app, I was interacting with the app on our test environment. I was interacting with the app with real services. Only our test environment wasn't that stable. Our APIs responded with two, three seconds of time. But I needed to test it on multiple devices. I also had some flakiness. Not each service on the test environment was that stable. I also had data. If I manipulated the data, I couldn't reuse it again. But I also had some troubles because I wanted to dive into the quality. I wanted to test errors. What would happen if a service was not there? What would happen if my response was not two seconds? But what would happen with the app if it was five seconds or 10 seconds? Could be possible in production. And what I also wanted to look at is if we're doing manual or automated tests, maybe I can also speed that up. So, this is what I... That's when I thought, well, we're gonna use mocking. Discuss this with the team. And I started with an application called NG API mock. You might be wondering, NG, people who are also automating Angular apps might know this module. It's a JavaScript module, especially for Angular. Well, I'm also a collaborator for this project and you don't need to use it with Angular. You can use it with each tool you want. And I'm gonna show you a demo here. For example, you have the app here. We want to log on, but we want to say I'm not authorized. I just change it in a menu and you will see an error message here. But I can now also test the default response but with a delay of five seconds. How would my app interact? And what you will see here is you will get a spinner. Now I've got my environment set up to also test extra stuff because in the end, when I'm testing my app initially and I want to test it on multiple devices, multiple OSs, I don't want to test my services. I'm not responsible for my services, at least not when I'm testing my app. I want to test my services but not on all the devices. It's a different phase. So testing the app, in our case, will be done with the mock server. Then animations. I think in the first movie you saw, there were a lot of bubbles and each bubble will take around 500 milliseconds to show. We have a minimum of 15 bubbles which will take us around seven half seconds. And if we complete the complete flow or walk through the complete flow where we have, for example, finger print, that kind of stuff, we have more bubbles. We have around 25. If we then also take an account that we have a delay between each bubble of 800 milliseconds, we have an average around 19 to 32 seconds and we're doing nothing. We're only animating. I've got a question to you. Can we automate animations? See a lot of people doing this, so I think I'm on the right track. Yeah. And no, we're not able to do that. And what you're seeing here, this is the first file. This is our complete app. If you're using React Native, you have an index file and there you're doing your basics. I had a few hours with a developer. We took a deep dive into the code and we saw that we were able to mock the animations. And mocking the animations meant for us that we could disable them. We could ask, hey, are you in animation? Are you being called to do an animation? Just put them to zero. To be able to do that, I needed to add a method. I called it setup automation at the top level of our application. So in this file, I put the method and eventually the method itself is very basic because it calls setup automation. And again, here, we are asking, are we in automation build because we don't want our animations to be removed from production because we want to give the user the nice experience. I'm also here disabling some error messages because it could be that there are some warnings. It could be in React Native that you have some warnings. It's easy to disable them because they're screwing up your automation. And at last, you see there the disable animation. And what we're doing here is we have a stop. The stop is listening to the animated timing component. And when the properties are called, we just return duration to zero and we set the delay to zero. And the result of this, you can see here, on the right side for you, you will see it without the animations and with the mocking on. On the left side, you will see our app, specifically it's a dev build or a release build with the animations and also the real services. We're done in 15 seconds. So quite again because the left side is still running and I need to keep talking before it's done. Hopefully we're there. No, we're not. We've got some animations here because it's not that nice. If you want to do the animation, here you will see you've got 40 seconds you need to wait. So we have a gain here of 25 seconds per scenario. So I think this was also a very good result for us. But then if you look at the app, the app itself, 95% of the functionality of the app is behind the onboarding flow. So if you want to do the animation or maybe the manual testing, you would see that the onboarding would be or the best test feature in the app or we needed to do some magic with the clicker. And we started doing magic not with backdoors because we also needed to automate our iOS app. Please. Yeah, we did some magic with deep linking and we started with the five features we had and how it works with deep linking. If you look at deep linking, maybe you've received sometimes an email that has a link go to your invoices. If you click on it, it will automatically open your app. Sometimes you need to log on because you're in a restricted place or you need to go to your user details. But that's how deep linking itself works. I was able to implement the deep linking because I already had mocking on the application because I needed to mock the state of the user. I need to say, okay, I'm just returning each user or just a common user, default user. The advantage of this was also that, yeah, I could go to each feature in theory directly. So all the developers who were just adjusting their source code to go to a feature were already happy with this. They didn't need to do anything extra. And if you just look at time, it saved us between 20 and 30 seconds per scenario because if you're automating and you want to go from scenario one to scenario B, you want to have a clean state. So if you have a lot of test cases, you need to close your app, open your app, but you want to start in your initial state, meaning I would go to my onboarding flow and I would want to prevent that. And I already implemented the first steps for production to implement deep linking. Well, how does this work? What you see here, the initial state is just onboarding. And if you're using deep linking on iOS, for example, you can just add it to Safari and we'll say I would like to go to home. You will get a pop-up and bam, here, I'm directly into home. This will save us that 20 to 30 seconds. So again, a step ahead for us for the automation. When that was done, we had kind of like a very solid framework. But then we had the first of the next steps. Teller 2 had bought the cloud solution. Then I tried my framework. I thought, well, now I'm gonna check if my... When that was done, we had kind of like a very solid framework. But then we had the first of the next steps. Teller 2 had bought the cloud solution. Then I tried my framework. I thought, well, now I'm gonna check if my framework will work on all our devices. Does it support parallel execution? And I found some flaws in my framework. I found out that first of all, needed to look at my test strategy. I also needed to look at deep linking because the way I've implemented it in the framework, it would not work on physical devices. And I also needed to reconsider mocking. So first of all, if we're gonna look at the test strategy, with React Native, we're supporting our platforms, iOS and Android, and we divided our devices into high, mid, and budget range devices. For end iOS and for Android, covering NDIA diversions and have a good coverage also based on screen resolutions. And we did that, yeah, we're a telecom company, so we know which devices our customers have. So it was quite easy to get the best coverage. If we then look at our test itself, we said we have specific tests where we want to validate, for example, text. But you don't want to do it on all devices. Those are only platform-specific, so you want to say I want to validate that the bubble will happen on an iOS device and also on an Android device. It doesn't matter which device. And we also have devices called all-device tests high-risk, we want to test it on all devices. So how did I do it? And this is kind of like how I misuse cucumber. I can use text. I can tag my test saying you need to do this on this device, you need to do that on that device. Basically what I did, just adding the tag. For example, I have here a scenario where I want to validate text. This will only be run on a device, and this was my average device, it was a mid-range device on iPhone 8, for example, but only we tested on that one and also on an Android device. The rest of the scenarios that don't have a tag will be run on all the devices. But what I could also say, if I have two tags in one for platform-specific, I would also tag it with all devices. So it was now quite easy, based on my test strategy, to select the right devices, but don't have a lot of extra code in it. It's only adding one line of, what is it, 10 characters. All right, I needed to reconsider deep linking. And why did I needed to reconsider deep linking? Because the way I've implemented it, it went boom. Not also in the app, also in my head. It's like, how am I going to fix this? The reason it broke was that normally when you're using Appium, when you're using deep link, you're calling the browser URL. On the emulator, it works. I couldn't get it working on a physical device, starting my app and saying to my app, go to this URL. It was not allowed. So I needed to do something different. I don't know how many people read the Appium Pro newsletter from Jonathan? Somebody? Well, screen you're seeing here, I send him my newest screen. I'll show you a world, I'll talk about it later. But I implemented a test link screen. I was able, because I had some good colleagues, I was able just to adjust the app for test animation purposes. Here I was able to adjust the app and click for example on a test link screen and saying you need to start in this state. So it's kind of like the backdoor we saw before, but in this case, I don't need to make a specific build or use the two apps to merge them together. I just have my automation build. I could click on the link and I was directly in there. So how does it work? If you look at React Native, you have a router. It's kind of like it tells you how to navigate through your app. And again, well, you see here a different line. You see your mocked environments. I could use this test link screen when I was on a mocked environment or a mocked build. We had a mocking build specifically for the developers which they could use. And we had the automation build I needed without all the animations. So if I'm a mocked build, then I would return this screen. Otherwise, don't return it because we don't want users to skip everything when we're in production. This saved us also a lot of time and eventually got a working solution also on the physical devices. But then, I needed to reconsider mocking. Why? Because first of all, not each scenarios is executed on each device. So this is the first thing we had. Secondly, not all devices have the same speed. If I'm testing on an iPhone SE or I'm testing on an iPhone X, could be that the iPhone X is much faster and all scenarios are done and the SE is still running. And all devices don't start with the same scenario at the same time. So what I wanted to prevent is that the API would get the same response. Otherwise, my tests would conflict with each other. I would get false positives or positive false. To tell you what I've done here, I'm first gonna dive a little bit into how did the mocking work. On the left side, you will see our app. On the right side, you will see our mock server. And what you normally do is you do a post from your app. You go to the mock server and you say, give me a response. Well, the default response that we've set up into our mock server is that you will always get a good scenario back. In this case, I'm saying I want to log on and it just responds here from our mock server. Thank you, Wim. And I can go further. But when I want to do this with automation and with WebDriver.io, I first need to set the state on the mock server saying to the mock server, if you're going to get a call on this service, for example, the token server, as we call it, you need to return unauthorized. And if I've done that with my automation, I will get a response back when he does a post. He will get a response back in this case saying, 401, I'm clicking now too much. Sorry, stop working the clicker. You will get a response, the unauthorized here. So this is a situation which we can test. But again, ah, sorry, he will get the response. But what will happen if you test this on multiple devices? Because I'm now saying to my mock server, just give, set the response of this service to unauthorized. If I do it on multiple devices, I get it back on multiple devices and I don't want it. So how should I fix this? I got an idea about this and I thought, well, what if I have something that is unique? A device, for example, an iOS device or an Android device, it has a UI ID or it has a serial number. What if I could use that part in my automation framework and also use that part to send unique API calls from the device, from the app itself to the mock server? And I did it kind of like this. When my test screen started, I retrieved the unique ID from my device. I saved it in my framework. And then when I'm doing a call, you will see something extra. I will hope I can zoom into it. In this case, you will now see that I have an extra ID. This is unique for the mock server because the mock server now knows, oh, when I'm getting a call with a unique ID, I need to respond with this unique ID. This response that needs to be there. So what you now see, the app is doing a post with the unique ID. It has the same unique ID already stored in the mock server and that's the connection now between them. So I did a little modification to the app, but not that big. And now I was able, at least there was my ID, now I was able to do parallel testing with mocking on multiple devices without interfering with each other. You might be wondering, how did you do that? Well, also with a piece of code, it's only four lines of code here. Again, we're here looking, are you an automation build? Because we don't want to add extra headers when we're on production. And what you see here, this method will only return a unique header ID which we need when we're on an automation build. If you then look at the configuration, we have a API config. And our API config will consist out of the base URL. We have headers, the default API headers. And in this case, we are returning the unique automation API headers. And if we're not an automation build, it won't be added. So that's quite nice. But how should I use it then? How should I retrieve the unique ID from the device and put it into my framework? Well, here's the advantage of my testing screen because what you're seeing there, it's now highlighted. That's why it's purple. But in normal cases, you don't see it. That's the element containing the ID because we are there also with a test property, added the test unique ID. And we there can retrieve the value. That's the value I'm storing into my framework. And each time I'm doing a call, in this case, this is the method to set the state onto my framework. And to my mock server, this is where you see the added ID. So now when my framework is doing a call to my mock server, it will say to the mock server, add that ID. Because if you're going to get a call, connect them. So eventually, when you look at it, it's kind of like this, only much faster. And this worked. OK, so now I'm almost ready. But there's the next phase. First of all, I've got all my devices now running. But what do I need to do now? And one of the next steps I need to take in this phase is, first of all, I need to reconsider the steps that I've created, all the test code I've made. For example, you just saw only five features. In the newsletter of Jonathan, I've created a new screen. At least I've added new features. And I can now reach each feature in our app with a single clip. Click. It will also speed up our tests so I can do more tests in less time. Also one of the things I need to do, I saw my colleague, I've got a manual tester next to me, doing a lot of tests with his hands. And when you're doing manual testing and you're looking at the device, you see 1,000 things at once. When you're doing automation, you're only focusing on one thing. So if I can do something with image comparison, I can just look at the basic screens where we see the highest risk of things breaking. Just pick that up and also put it in the build. So that's one of the next phases. So if you look at all the steps that I've taken from our framework and you look at each scenario, I already had a gain of eight seconds when I moved all my mocking or all my real services to the mocking because I could give back an instant response. And in each feature we use around four API calls. If you look at the animations I've put in here, I save around nine seconds per scenario. If you then also look at the deep linking part or the test link screen, I also save here around 15 seconds. So if you count that together, you will get around 30 seconds already what you're gaining with all the steps we've taken. We've got 65 scenarios here. So yeah, that's quite what, oh, sorry, something happened. Oh, something went wrong. I just saved 30 minutes here in my execution time. 30 minutes without doing anything. So I think that's quite an achievement if we look at the execution time at all. But, oh, something went wrong again. I'm gonna explain this one, it's a lot of text. With the parallel execution or with the test cloud we are now using, we can do the parallel execution. When I compare it to what I did on my local machine, I had all the tests around, it was costing me around 25 minutes. And I got all my scenarios tested. I got the complete app tested. Now I'm able to do it in 30 minutes but with four devices. Testing all the same scenarios, yeah, based on the test strategy I've explained before, but that's only an increase of 15% in time. And I think that's also a nice gain if you compare it to normal development. And yeah, this is how I made React Native, Appium and myself shine. But if you go back to the pros and to the cons, what were the advantages of doing this? Well, first of all, I was able to increase the quality because I was able to focus on the stuff that really needed to be tested. I could also speed up development so the developers were also glad because they could go to their application or to their feature directly. We could also test, for example, our error states. What would happen if I do four service calls and the first service call would fail or it has a delay? What was the effect on the second service call? What was the effect on the user experience? We were not able to do that when we were using live services. And yeah, in the end, I was able also to speed up the execution time. There are also some cons. People are saying, well, you're not testing the real services and yes, you're right. People are saying that I'm not testing the real services but in my opinion, if you want to test your app with real services, you're talking about integration test. And in this case, I don't want to test my app. I want to test it not in an integration phase. I want to test it before we go to other environments where we have real services. People are also saying, yeah, the app is not a production app but I think what you've seen here, there are only a few lines of code added which speed up everything and it doesn't have a large effect on the app itself. And one thing, one con, I had a colleague who was debugging his app or the app feature for over an hour because he did not saw any animations. Was wrong because he was using the wrong build. So that's the only con you can also have, just use the right build. Well, I hope we have some time for questions. So if you have questions, feel free to ask. No questions? It was clear, cool.