Detox 101: How to write stable end-to-end tests for your React Native application
From Author:
Compared to unit testing, end-to-end testing aims to interact with your application just like a real user. And as we all know it can be pretty challenging. Especially when we talk about Mobile applications.
Tests rely on many conditions and are considered to be slow and flaky. On the other hand - end-to-end tests can give the greatest confidence that your app is working. And if done right - can become an amazing tool for boosting developer velocity.
Detox is a gray-box end-to-end testing framework for mobile apps. Developed by Wix to solve the problem of slowness and flakiness and used by React Native itself as its E2E testing tool.
Join me on this workshop to learn how to make your mobile end-to-end tests with Detox rock.
Prerequisites
- iOS/Android: MacOS Catalina or newer
- Android only: Linux
This workshop has been presented at React Summit 2022, check out the latest edition of this React Conference.
FAQ
Contributors can get involved with the Detox project by fixing bugs, developing features, or enhancing the framework's functionality. Interested developers should look for issues labeled 'looking for contributors' in the Detox repository and follow the contribution guide provided by the project.
Detox provides several debugging tools, including detailed log levels, taking screenshots, and recording videos of test sessions. These features help identify the causes of test failures and verify the application's behavior during testing.
Yes, Detox supports cross-platform testing, allowing the same tests to be run on both iOS and Android platforms. It includes support for handling platform-specific elements and gestures, making it versatile for testing mobile applications across different devices.
Detox addresses test flakiness by synchronizing with the app, waiting for it to go idle before proceeding with tests. This approach ensures that tests only run when the app is stable, reducing the likelihood of failures due to timing issues.
Detox is an open-source end-to-end testing framework developed by Wix to address issues like slowness and flakiness in test automation, specifically for mobile applications. It is designed for React Native and provides stable testing by synchronizing with the application.
To avoid flakiness in Detox tests, it is recommended to use unique identifiers for elements, ensure tests are independent, start tests from a clean state, and use proper synchronization. Additionally, running tests in parallel and using the retry option as a last resort can also help manage flakiness.
Video Transcription
1. Introduction to Detox and Test Automation
Welcome to our Detox 101 workshop. Today, we'll learn how to write stable, end-to-end tests for your React Native application using Detox. Detox is a gray box testing tool developed by Wix to solve the problem of slowness and flakiness in test automation. It is different from other frameworks and popular in the React Native community. Detox allows you to access memory, read application state, and sync with the main thread of your application.
So, hello everyone, and welcome to our Detox 101 workshop. I'm super happy to see all of you here. Today, we'll actually try to make it hands-on. We'll try to practice a lot, and then learn the tool. And we will actually learn how to write stable, end-to-end tests for your React Native application.
But first, let me introduce myself. Hi, my name is Yevgenia. You can call me Jane. I'm from Ukraine, and currently in Ukraine also. I'm a QA manager in Wix, and my main focus during the last few years was actually on developing strategies, best practices, education, and test support for test automation in both web and mobile in Wix. And for web we have our internal solution, and for mobile, as you might already know, we have our open-source end-to-end testing framework for mobile applications, which is called DtoX. And we will be talking about it today. Also, I'm an authorized instructor in ICA Agile, and I'm a founder of QA School in Ukraine, where we educate QAs how to do good test automation. I'm also a public speaker. I'm usually talking on QA conferences, but you guys invited me to do the challenge and do a workshop on a DevConference, so it's my first time. Wish me luck. And I'm super actually excited to do it. And I'm a crazy Corgi lover, especially loving this little guy. His name is Ruby, and he is somewhere around us today. He was actually named after a programming language, so he's one of the participants. But he's not the topic today. Today we're here to talk about detox.
And since we're talking about testing tool, before starting to switch to the tool itself, it's also worth to say that we have today an amazing detox team with us. Full house. Guys, please say hi. Great. So, we have Amit, Asaf, Joseph, and Jonathan. Thanks a lot for joining. Guys, we'll be actually here to help you during the workshop. In case you're having any issues or questions or anything, you're always welcome to post them to the Discord channel created for this workshop. It's called RSH Detox 101 and it's dedicated to our workshop. So in case you're facing any issues during the workshop, they will be there to help you. And also I've posted a message there called For Q&A. If you have questions that you want to get an answer for like, what is your next feature I reported some bug when you're going to fix it, or like how can I contribute, we will save time in the end for the Q&A. So just put it into the thread. And again, don't hesitate to ask for help in case. Okay. And let's just stay muted. I will go through the flow of the workshop and guys will be there for you in Discord to help.
Before actually starting to talk about again, end-to-end testing and tools, it's worth to remind about the primary concept in that's automation, you might have already saw it before. It's a concept of basic automation pyramid. So what it actually says is that we should have multiple testing levels in order to cover our application in the most cost effective way. We should have as many unit tests as possible, because they are testing the code itself, the exact functions. They're the cheapest, the fastest, so we can have as much as possible. Then we should have a smaller amount of integration tests. And it can be regular integration, it can be component tests, and some other intermediate levels. We should have less of them to connect those units together. And then we have end-to-end tests for anything else that is like remaining. And end-to-end tests, we kind of think that it should be the smallest amount of those, because they are actually connecting the dots acting like a real user by just literally pressing buttons on your application, visually checking something and such.
In this case, when I usually talk to devs, because I work a lot with development groups in Wix. I hear that they use uni tests a lot, I hear that they like integration tests, but I almost never hear that they love to write end-to-end tests. And usually, end-to-end tests considered to be problematic. And the reason for that is usually flakiness. So sometimes, since end-to-end tests are related, they depend on many, many circumstances. So there they depend on the, even the connection, the other modules that you're testing, internet third parties, everything. Because they're literally doing it like a real user. So it means that you end up with having your tests flaky, and even because it was not like your problem. And the good thing is that Detox was actually created with this problem in mind.
So please meet Detox. Detox was developed by Wix to actually solve the problem of slowness and flakiness in test automation and used by React Native as it's own end-to-end testing tool. So to explain why, like, and how Detox is different from other frameworks and why it's like popular in the React Native community. The first thing is that Detox is gray box and not black box. You might have heard the terms like, black box is when you are testing something like a real user, you have no idea what is going on under the hood and white box is when you know everything and you kind of know how each function works, so it's usually close to unit testing and such. But there is also an intermediate concept in between, which is called gray box. So gray box is kind of when you know something about how your system works under the hood and you can work according to it. In terms of test automation, when you look at the black box, black box is kind of when you know only about the UI hierarchy of your app. So basically you know what are the components that you have over here and you know that you can interact with them. This is it. You don't have anything else. But when we are talking about the gray box concept, you can access memory, you can read application state and you can actually sync with the main thread of your application.
2. Introduction to Detox
Detox is a cross-platform framework for writing stable, end-to-end tests for React Native applications. It synchronizes with your application, waits for it to go idle, and prevents tests from failing due to ongoing processes or animations. Detox has first-class React Native support and does not rely on WebDriver. It allows you to write unified tests that work for both iOS and Android, while still supporting platform-specific code. Today, we will be using a demo project, a basic movies app, to learn and practice writing tests with Detox.
So what does it mean in reality? The way detox works, it synchronizes with your application and working by this super simple graph. So it waits for up to go idle and like continuously every like millisecond checking, if app is idle and in case it is not, it will still wait until it will go idle. And only once it is, it will proceed. And basically it will prevent you from failing on many, many cases. You are entering some screen, you had to lower the running, and like especially happens a lot on web, you just press the button which was not present and your test failed because your app was still like doing some requests or like still loading some animation or something and app they can test failed because app didn't actually play. This framework didn't actually wait for app to go idle and deduct does it. So it saves a lot of tests from failing and makes it a lot more stable. Another thing is that D-tox is cross-platform meaning you can write the same test, it will work for both iOS and Android, which is super great. You can also have some platform specific code like using some platform specific gestures or some specific like components that only like iOS have or Android, but still you can use something unified and still have one test that will run for both Android and iOS, which we will actually try out today. D-tox does not rely on WebDriver, it was built for mobile applications from scratch and it has the first class React Native support. And today we will be actually playing with it a bit. We will use the React Native app to do everything with the D-tox, and this is actually D-tox in action. I will be showing you the writing tests today, and we will be in, like, the detailed agenda will be in a few minutes, but we will try many different actions learn some tips and best practices, and here you can just see the way it works. So we will work with the demo project that I've prepared for this workshop. It is a super basic movies app. I hope you love movies, because I do. And this app was prepared for the workshop. It is super easy, and it has some components added, so we will play with it. And I really hope that you had a chance to clone it already. Install everything, and, like, made it work. In case you didn't, please do right now. You have the link in the Discord Channel in the top, so just find it and make sure you follow the prerequisites, so we can... I highly encourage you to do it hands-on with me.
3. Workshop Agenda and Setup
Today, we will set up Detox for iOS and Android, learn about writing tests with Detox, and explore running tests in different ways. We will also discuss tips for avoiding flakiness in tests. There will be a Q&A session at the end, and we will have breaks throughout the workshop for refreshments and questions.
Cool. Today, in our agenda, we will do, like, four main things. First thing is we will do the actual setup of the detox. We will configure the detox for both iOS and Android. We will... Like, for iOS, it will be pretty easy, but for Android, it will be a bit more, like... More actions, because we'll need to configure our native project for Android to work.
Then, we will switch to writing tests. We will play with different, like, concepts we have in detox. We will play with matching the element, doing some different actions, doing expectations. And then, in the third part, we will be actually running our tests as many different ways. We will learn how to run them in parallel, we'll learn how to debug a fail test, what are the CLI commands that we have to do that. And we will also learn some tips about flakiness, like, how to write your test so they won't be flaky, because every testing framework is not the magic. It does all the best that it can, but we still need to write good tests, so they will be not flaky.
And like I said before, in the end, we'll have some time for Q&A, so in case you have questions, there is a message in the channel for Q&A. Just post your questions into the thread or save them for the end. We will, like, open room for anyone to ask. And again, we will have a little structure for this workshop, like three hours is a lot. We'll do two breaks. We'll do one hour, ten-minute break, another hour, again, ten minutes break, and one last hour, so you can grab some coffee, fresh up yourself and come back. And again, I will be here during most of the breaks, so in case you're having any issues or something, first, don't hesitate to ask in Discord. Second, you can wait until the break to ask them in person.
4. Installing Detox and Configuring Detox RC
We will start by installing Detox and configuring the Detox configuration file for iOS and Android. I will guide you through the process and give you time to complete the steps on your machine. We have a React Native app with two folders: one for the application and one for cheat sheets. Make sure you have completed the prerequisite steps and have the necessary dependencies installed. We will be using the latest versions of Detox and Jest. After installing Detox and Jest, we will initialize Detox using the Detox CLI. Template files will be created for Jest test runner.
Great, are we good, guys? Please give me some reaction. I will be using reaction mechanism with you to see that we are good. Just give me some reaction, that you still listen. Okay, great, perfect. Okay, cool. I won't be seeing all reactions, but I will try to switch. Cool.
So let's start with the first part. We will actually install DTalks. We will configure the DTalks configuration file, and we will do iOS and Android configuration. In case you're doing only one platform, just stay with us because another platform will take some time. But I really encourage you to do both in case you can because it will be most interesting, I think. Great, so I'm switching to my VS Code. The way we will work is I will be showing you something, and after that, once I show you something, I will give you a few minutes to do it on your machine, and then once you're done, just give me some reactions that you've done, and I will go further.
So this is the project that I have. I'll show it to you in GitHub. Jaroslav already sent a link to the channel, again, so you can get it. Basically, this is a React Native app with some movies shown, and the important thing to explain in here is that it has two folders. It has the folder for the application, this one, and it also has the folder for the cheat sheets. So cheat sheets are basically the kind of like cheat sheets with list of the commands that I will be using during the workshop, so you can open them and just copy-paste and no need to type after me. This is the one that I already sent to you about starting the project, and installing everything, and starting your iOS and Android app, so I hope you did it already. In case you didn't, make sure you at least run NPM install and installation of pods, so we can proceed. We will work with other cheat sheets later on. Another thing to show is that it has multiple branches. So we have a branch master will work. In this branch we have with detox set up, which already has detox setup, so like after first hour of the workshop. So in case you're stuck, you're not sure why it's not working for you, or what you're missing, you can always switch to this branch with detox setup and continue from that point. And with tests is actually having the final result of our workshop, like with test written and everything like configured, you can use it as a reference after the workshop, in case you want to try it in your project, or you want to work somebody else, you're super welcome to use all the materials that are coming from this workshop.
Cool. So I think we are good to go. I'm switching to my VS Code and I ask you to open this first cheat sheet in this like folder below. You see, there is one detox setup, just open it like I'm opening it in preview mode, like on the right side, and the first thing that we will actually do is we'll actually install detox. So during your prerequisite steps, you should already installed the detox CLI, which we will be also using, but we also need to install the detox as a dependency and install test runner for detox. So let's just do today. Again, I'm showing you explaining something. Then they give you a minute to do it on your side and you give me some reactions that you did it. Okay. So let's go to the folder and let's hope nothing goes wrong. I'm switching to this folder and literally just copy paste the command. So you will be sure you're doing it correctly. First thing I just installed detox as a dev dependency. You can work with the latest versions always. In case there are some issues, I will also post afterwards, the detox repo and detox discord. In case you're having any issues or questions, you can join and ask. This is actually the first thing that we will do. Detox installation will take some time. So now you can actually switch to do it on your machine. I'll give you a minute. Just use this first line and install detox on your machine and give me some reaction once you're done. I hope somebody will be doing it hands on with me today. Detox CLI was actually part of the prerequisite steps so it should have been installed already. But in case you didn't, make sure you go through the start the project zero cheat sheet and check that you have everything while we're doing this and talking. I see some reactions, so I hope you are good. Cool. The next step, we are installing Jest. Again, I'm copying this command and installing it here. I'm installing the latest Jest. So, it's already working with Detox. So basically, Detox, before and now also, it was test runner independent, meaning you could work with any test runner you want, like Mocha or Jest. But we highly recommend using Jest because in future, we might stick with only Jest usage and that's why we highly recommend, in case you're setting up your project right now, just use it with Jest. In case, for some reason, you need something else like Mocha, you can also find examples in detox repo where we have some example projects and you can find there a Mocha setup. Cool. So, just do it around your machine and give me some reactions, it's all good. The second line was installing the Detox, sorry, the Jest. Let's switch to the next step and the next step is actually to init detox. So, for this one, we're using the Detox CLI already. So, in case you don't have it installed, you'll get an error and in this case, just make sure you go back to the start project, find the line about the Detox CLI and install it. So, pay attention to my screen. Once I will run detox init, template files will be created according to Jest test runner and I will get four files created. So, what you have on the left is you will have E2E folders created, which has three files, and you also have the Detox RC JSON, which is a configuration file for detox.
5. Configuring Detox and detox RCJSON
Configure detox by updating the detox RCJSON file for iOS and making changes in the native app for Android. Detox has many configuration options, and you can find examples and guides in the Detox documentation. Open the preview to configuration file and copy its contents into the detox RCJSON file. The configuration includes specifications for apps, devices, and configurations. Make sure to replace the necessary values with your own. The file contains configurations for iOS release and debug, as well as debug and release for Android. It specifies the build type, binary path, and build command for each configuration.
So, do it right now and after you're done, I'll start explaining and we'll start configuring detox. So, take a minute and do it.
Okay, cool. Guys, thanks for giving me reactions because I need to somehow understand if you're still listening to me or not. And, cool. So, I hope you're done with it because it was a super small command. So, now let's check what actually we've done. So, we've created four files. So, first one is a config JSON, which is actually like a configuration for our runner. You can see here, like, the most important lines in here is the amount of workers which will be relevant for the parallel execution. Like, later, later on we will talk about it. Then you also see this test runner specified. We're using just Circus automatically for this project. Also, there is a test timeout. It's basically the timeout of your test to wait until it fails because it couldn't do something or it couldn't, like, some, I don't know, infinite animation or something. So the 120 milliseconds, it will wait until it will actually fail because of the timeout. And then important thing is that there is a test regex to actually where your test files are placed. So in case you are, like, changing the structure, remember to update it here also. Then we have an environment file, which we won't touch, and we, like, don't actually need a lot of attention there. And let's just switch to this first test, E2E. So first test, E2E, is actually template files, template tests that will make no sense for our application, of course. But still, you can see example here of some tests that is, like, expecting for something to be visible, then test stops on something, checks for some tests and such. We'll modify those tests to work for our application a bit soon. But just leave them as is right now. And then we have our last file, which is DetoxRCJSON, which is actually a detox config. So it mainly has three parts. It has the three important parts. It has the apps specification, meaning like the your iOS build command, your iOS application path, your Android build command, your Android build path and, like, whatever other builds you need. So if you need debug builds for iOS and Android, or you need release builds for both, you specify them over there with the exact commands, like your regular build command that you use for your app. Then you also—we will do it in a few minutes—and then you have a devices part. So devices are actual simulators or emulators you're having on your machine. The example will have my own simulator, so you need to replace it to have yours. And then we have configurations, which are actually a combination of device and the app. So here you say, okay, let's say I want to have iOS release configuration, and it will say I want to build my iOS release and install it on my iPhone 12 or something like this, and you can kind of do the combinations of whatever you need. Great.
So the step two is actually to start configuring our applications. So for iOS, it will be extremely easy. We'll just need to update our detox RCJSON, meaning to put like valid configuration in there, and for Android it will take a bit more time, because we will be doing the changes in the native app itself, but like, no worry, so just go with your step-by-step and we'll do it. And just please open. Now you can do it like in weascode or somewhere else in other monitor, you can open this preview to configuration. This file is pretty long. It has everything that we need to configure, and afterwards you can also use it as a guide for your own project configuration. So first thing that we will do is we will actually open our detox RCJSON file, and we will start configuring it. Actually, detox has a lot of configuration options. You can see a link in the top of the document. Actually, detox looks at many types of configuration files. It looks at DetoxRc, the JS by default and RCJSON. You can also, in another popular way, you can also put a detox section in your package JSON in case your configuration is like small. For instance, you're running iOS only. Then you can actually see all other configurations that you can do. Actually, Detox documentation has a lot of guides and a lot of examples. We will literally be copy pasting from it today and you can do the same on your project. Now, let's just start configuring the first part. On the right you see we have this whole JSON file prepared already. Let's just copy it and paste into our Detox R-C Json. Just take your minute and do it right now, and I will explain what we have inside this file. Please give him your reactions again so you're done with it and I can continue to the next step. I see some reactions. Great, I hope you are still with me. The thing that I've pasted here is actually a pretty big configuration. I have here four applications config. I have iOS release and debug, and debug for Android and release for Android also. You can see here that I have three main things. I have a type of the build, I have the binary path, where my exact application will be after I do the build. It's like pass to your dot app file, and then you have a build comment itself. You can put here your regular build comment or you can try using mine. Just replace the name of your project once you will be doing it on yours. The same for the debug for iOS. In Android, it's pretty generic. You can see here that we do the assemble debug build, and we also assemble Android test, which is important for detox.
6. Configuring iOS and Android
Make sure to update the devices in your config file for iOS and Android. For iOS, get the names of your simulators from Xcode. For Android, use the command 'emulator -list avids' to get the exact AVD names. Start the build process and configure Android while it runs. Run 'detox build -C iOS sim debug' to start the iOS build. If any issues arise, ask for help in the discord. Once done, move on to configuring the Android project by editing the build gradle file in the Android folder.
Make sure you're not missing it once you're doing it on your side. But for us, it's basically configured. The next thing that they will ask you to do is actually to update your devices. This current configuration has my devices in here, but we will need to replace it to be yours. In order to get the names of your iOS simulators, you can actually open it from Xcode, and see like this, like right-click and there is device. You see there are the names of the exact devices that you have. Most likely if you have the latest Xcode, you can have iPhone 12. You can leave it as is. And for Android, it's a little bit more complicated to get the list of your simulators. You can either go to Android Studio, which takes a long time, or you can run a simple command called emulator minus list avids, and you will get the exact name of your simulators by AVD name. This is important that in here, you put the exact AVD name of the simulator that you have in your system, and just copy paste from here. And in case, you will have just Pixel 5, it won't find it, you need to have the exact AVD name. Cool, so just now, I give you, take a minute and update the devices to be the correct ones on your config file, and this is actually it for iOS. We will start the iOS build right after that. Cool. Yeah. Okay. Okay, cool. So I see some reactions, so I hope that we're good. So now, the things that we will need to start is actually, we will start the build. Build will take a lot of time, so during this build process going, we will be setting up Android in our side. So let's just run the build from the detox CLI. So the way you do it is you just check what are the configurations that you have. You can change the names, you can decide like which are the ones that you want to have. And basically, in here, I have four configurations. I have iOS SimRelease, debug, and Android Debug and Release. I will be using only debug for this workshop. And the reason for that is we will be changing our app. And just like when you do the development, I want it to be updatable, so I will use the debug build. And it's like the better practice probably for local development. Once you're running and writing your tests while writing the app. But once you're doing it in your CI, and detox is actually designed for CI, so you can do everything from like command line, and before the release, of course, it's better to do the build in release configuration and run your test the same way. So the thing that I will do, I will start my build. I will do detox, build, minus C which is for configuration, and I will put iOS sim debug. I will just copy paste from here, so I will be sure. So detox build, minus C iOS sim debug. And please take a minute do it on your side and make sure it doesn't fail from the first line. But in case it does just post a question to the discord and we will help. And give me reaction once you're done with it. Not once your build is done, but just once you started the command, please because it will take a lot of time. Okay, my build failed. Okay, cool. So let me just check. Sorry, I think I have some issue with the simulator, just a sec. Okay. But could go wrong of course on the live demo. Okay, cool. Let's just do it. Okay, I'll run my build a bit later on just to see, just a sec. Let's fix it on my side to see everything is okay. Build yes. Okay, I have some issue in here. Okay, so I'll start configuring Android and I'll fix it a bit later on. So, let's see if I'm like right now on it. So let's just start configuring Android on our side. So the next thing that we will have is actually we will configure the Android project. So to do that you just say. Sorry, just saying, well, I started from your branch and it builds well on my machine. Yeah, yeah, yeah. It's just, yeah, it's something I need to fix in myself. Don't worry, I'll just do it in a second once we will do the Android configuration. Sure, cool. So far I can see it works. Yeah, okay. So let's just start the Android configuration and then like once the break, I'll just run my build. Cool. So what we will do is we will actually go to our exact Android folder and in the Android folder, what we will do is we will start configuring our build gradle file to add some detox configuration. So just start with opening your build gradle, this one from the root of Android. Make sure you're opening the root one because we will need to edit both. And in here you see we have this X section and we have our dependencies.
7. Configuring Kotlin Version in build.gradle
Copy the Kotlin version from your Android Studio preferences and paste it into your build.gradle file. Replace the existing Kotlin version with the one you copied. Let me know when you're done.
So we will need to paste one line into this X part, just copy from this right side like Kotlin version, blah, blah, blah. Just paste it in here. And what you'll need to do, you'll need to replace to the exact Kotlin version that you have on your machine. So the way to check it is actually to go to your, like, it's a bit stupid, but you need to go to your Android studio, you don't need to open any project. What you just do, you click Android studio, preferences, and under the preferences, you have languages and framework and you have Kotlin. So in here, you have this current Kotlin plugin version. You can ignore 2.1.1. So just put this 1.6.21, copy it and just put it into your build gradle. So take a minute, do it right now. I will leave it here so you can find wherever you have it, and just give me some reaction once you are done with it and I will just fix my build during this second.
8. Configuring Android for Detox
Add class pass Kotlin gradle plugin and Kotlin version in dependencies. Edit app build gradle file and add dependencies for Android. Create detox test Java file and paste pre-created code. Update package name and remove optional test Butler Probe. Enable clear test traffic for detox by creating network security config xml file and adding it to Android manifest. Modify test file to match expect element by specific text and run the test.
Great, so the next thing that we add is this class pass Kotlin gradle plugin, Kotlin version in here in your dependencies. So please add it right now. And then in other things that we'll need to do is also to manage the change our all report, all repository section, which is like below. So please add this line into your dependencies and then copy these two repos in here and put it in here. I will replace Google because I already have it. So you need to have these two under the repository section. So please do it right now and give me the reaction that you are good.
Okay, cool, so the next thing that we actually switch to is we need to also edit our app build gradle file, which is placed under the app folder. Make sure you save and close this one and do not mess up with, between those and under your app you also have a build gradle, just open it and we will also need to do a few bastings in here. Cool, so scroll down to the bottom of the file and a bit up, and you will see there is a dependencies section in here and we will need to add two dependencies for Android. We will need to add some test implementation which will actually allow us to work with some test applique that I will talk about in a few minutes, so just paste it in the beginning of your dependencies or in the end, doesn't matter. Just add these two lines and then you also copy this second part, you see these two lines, and you paste them into the default config section. You can search for it, but it's like in the top of the file, and right after like this part, just put it in here, fix some spatial issue, and these are two lines that are needed in order for detox to work with test applique because in reality in Android, detox needs two applique files, the real one that you build and also the test file so it can work with it. So take a minute and please do it right now and give me a reaction that you are good with these two.
Okay, I see you are super fast, awesome. Okay, so just one more second, then switching to the next one. So next step is a bit more complicated. We need to create a detox test Java file, detox test class, and we will like, we need to be sure that we're using the exact correct path that I have in here. So you go to your app src folder, and inside of it, you need to create this pass ending up with your package name. In our case, our package name is detox workshop lowercase. And like here you have it in a default config, and just make sure that your path is correct. So I'm creating it under the src create a new folder, I'll just paste it like this, and also put the detox workshop in here. So this is the final path that I will have, and press Enter. Do it please, right now. So because it's like a bit of messy stuff, so we won't break anything. Just do it and okay. I see people are done with it. Cool, I love it. It's like you're really fast. I was worried that it will be too boring to do it together with me. Okay, cool, and now what we need to do, we need to open the link in here, and it opens the example project from detox repo. And we literally need to copy paste the whole file. It's already like pre-created, you don't need to design it on your own. So just copy the whole file. Just look at, pay attention to whatever I have, and then go to this detox workshop folder, and create a file under it, which will be called detoxtest.java, like this. Make sure the exact name of the file should be like this, and then you just paste everything that you copied from that file in here. Do it right now, and then we will modify it a bit, so it will work for our project. Okay, okay, cool, let's see, okay everybody is done. Okay, cool, I see reactions, great. So, after you pasted it, we need to update our name of the package in top. So, again, replace it with detox workshop like we already did in the folder. And the second thing you need to do is it's an optional stuff on your project. I will remove test Butler Probe. It's actually a thing that helps you to debug failures and crashes on your app better but we won't use it for this workshop specifically so I will just remove it so we won't get any issues during the build and just save. So this is kinda it. Cool, so this is it what we need for this file. Again, give me reactions once we're done and we will proceed to the next step. Awesome, and my build is still running so we have time for one more step. So last step is actually to like enable the clear test traffic for detox from I think Android 28. It was like disabled and detox actually needs to access the traffic. So that's why we will do a little configuring. So we go to SRC, inside of the SRC we find main res and here we need to create our xml folder so I'll just create a folder like this and inside of this folder I create this file the network security config xml, so just copy the name and create it under your xml folder just like this. And the only thing that you need to add in there is the same just let me close the remaining stuff and you can take this minutes to do the file and the folder and my computer is saying it's too hard for him. So okay what you need to do is you need to actually okay you need to actually copy this part xml version blah blah blah first snippet into this file and save. So do it please, give me reactions that you're done. Cool, now I'm feeling a bit like a blogger today with asking people to give me many reactions on go. Okay cool, cool I see. Okay amazing. So last last thing that we do is we actually add this file into our Android manifesto. So just copy this only line and go to Android manifesto which is super close to this file and inside of it, let's put it in here cool, and inside of your application so in this part just before the last closing tag, just put it like this and we are done with our Android configuration. I hope you're still alive because it's the most boring thing I hope you are not too much bored but that's actually it and my build have actually succeeded so we can actually try to run the test. So since you remember that we've created this template test which doesn't make any sense for our app and I want my test to be green from the first run so what we can do is we can actually remove these two tests and what I will do is I know that my app has a text called trending movies in here so I will just modify my test, my only test to match expect element by specific text, sorry, trending movies to be visible and I will just run it afterwards. So please open this test file, modify it like this so we'll have it green and give me a reaction so I can start running the test. Mhm. Mhm. Okay, okay, I see. Cool, awesome. Okay, okay, so, great and now let's run our test so to run the test we need the exactly same command we used for the build, only thing we replace is the build word to the test word. So just do it like this and I will close Android Studio so my Mac won't just blow and actually I will press enter and it should start running my test. So I have my simulator in the background so I will just start it manually so you will also see it.
9. Writing Tests with Detox
We have completed the configuration for Detox on both iOS and Android platforms. The build is successful for both platforms, and the tests are green. From now on, we will focus on writing tests with Detox. We will learn about measures, actions, and expectations in Detox. Measures are used to find elements on the screen, similar to selectors in web automation. Actions define what actions to perform, such as tapping, scrolling, and swiping. Expectations are used to check the state of elements, such as visibility, focus, or text. It is important to have expectations in your tests, and each test should check only one thing. Let's start with measures.
Okay, okay. Okay, mm-hm, mm-hm. Oh, yeah. So it already actually installed my application. I will rerun it so you can see it again and then we'll go into details about what's happening in here. But the good thing is that we have the first passing test so good for me, it went well. Just do it right now on your machine, please. Run the first test, make sure it is green, give me your reaction. So just a little tip in case you are running and your simulator name is incorrect. So in this case, detox will fail but it will give you kind of a tip like this is like not the actual names that you have and these are the simulators that you have so you can copy from there and just put it into your Detox RC file to configure it to run on the specific one.
Great, so actually our first part is almost done and the last thing that we'll need to do is to build our Android project and actually start the test but I propose to do start the build right now and go to break so we'll be back once the build is done and we can run our test once again. So again, I'm doing the detox build minus C. In case you will run without minus C specifying your configuration, you will just fail because it will say that there are multiple configurations like this and if somebody is facing any issue during the break we're here so I will be leaving only for a second so I will help with the issues. So you run detox build minus C and then again just copy from your detox RC because not to create a mistake like this and just run it and that's it for the first part. So I think we can start the second part so we've actually done the whole configuration that we need. We've installed detox. We did the detox configuration for both iOS and Android. My build is actually green so which is great from the first try and now I will just run the same thing but just to see that my detox test for Android is also okay. So please just do it together with me. Just run your Android test. It should actually start your simulator and install the app the same way it did for iOS and the test should look exactly like the iOS one because it's the same test.
Okay. Mm-hmm, cool. Okay and apps reloaded, cool, and test is green, great. Android is also green so we have two green tests on different platforms which is amazing. So from this point actually I will switch to using only iOS because all tests will be right and will be cross-platform. So in case you want, you can also switch to using only one platform, either iOS or Android, whatever you like. I will use iOS, but again if you want you can keep using both, and I will just be using only the iOS one. So I'll put it somewhere in here so you can see it all the time. Okay, great. And we will actually, in this part, practice how to write tests with Detox. So we will learn how the Detox test actually looks like, what it consists of, the basic syntax. We will learn how to find the element because in case, like, we have some best practices that I will talk about, and some other tips and tricks that you can use in case you cannot use the best practice. We will talk about three main concepts in Detox which are measures, actions and expectations. And we will also try how to do platform specific actions in case you need it or in case you're, like, working with only one platform and such. So you will be able to write, like, one test and it will literally work even with platform-specific steps for both platforms.
Cool. So guys, give me please some reaction that your tests are also green and you are ready to continue from this point so I can start showing you the test writing part. Okay. Green, green, cool. Okay. I see more people actually giving reactions, which, like, makes my mood even better. So, and now I'll just switch to test writing. So we have another cheat sheet for this part also. So just open the third one in preview because in here you will see some best practices, links to the documentation also. You will have some, like, examples of the code and I really encourage you to use it after the workshop in case you will want to write some tests. And what we will actually start with is, you can, like, open it somewhere else. I will just start with showing you a cool place to go in case you're starting to write your tests with DDoS. So we have documentation, like, API reference for three types of things in DDoS. We have measures, we have actions, and expectation. Measures are the way you kind of find your element, like selectors in web. I will be also comparing with web a little bit in case you're familiar with other types of automation. It's like, other frameworks are more web like, so I will be comparing with it. And this is like selectors in web. A way to kind of find your element on the screen. Then there are actions, which are, like, what you want to do, tap, scroll, swipe, whatever. And you can also have expectations. You must have expectation in your test, which is actually kind of the purpose of your test, is to check something. And you can expect some element to be visible, to be focused, or to have some text, et cetera, to have like any type of expectation that you want. Make sure a good test always has the expectation, and it ends with the expectation, so make sure you have it, and you check only one thing within your test, which is always a best practice. Cool. So we will start actually with talking about measures. So I will close this one, so you will see better. Basically, let's look first what this test does. So, I have a typical JustSyntax that most likely you're familiar with. We have describe, which is kind of a test suite, like all your tests that you have in this file. Then you have a beforeall and beforeeach statements, which is the code that will be executed before all tests, like only once, or before every test that you have. So, in here, you can see that before all tests, I'm launching the app. And before every test that I have, I am reloading the React Native. So, in case I will run my test, let me show you.
10. Tapping on a Button and Expecting Text
In this part, we learn about the importance of starting from a clean state in our tests and how to tap on a button and expect text to be visible. We also discuss the significance of using test IDs to match elements in Detox tests.
So, you will see that it kind of opens twice because first time, you see that it's being installed on the simulator. And once it is, it opens it, it launches it for the first time. So, it's beforeall executed and then it's reloaded it because reload React Native worked and then my test was actually working. So, we will need it in case we will have multiple tests because it's always the best practice to start from the clean state. In the end, if we will have time, we will play with some flackiness stuff. I'll show you how to make your test not stable, like dos and don'ts with your flackiness. We'll play with it a bit later, but just FYI, that's why we need it.
And then, we have our test, which is under the it statement. And I will just rename, I will start with some super basic tests that will tap on this button and expect this button press text to appear. So, in order to do that, I need to tap on yellow button. By the way, if you are feeling like you're bored, you can always play with it and try it before I do it and then compare with how I'm doing this and to play with it, if you're waiting. So you need to tap on yellow button and expect text to be shown. So to do it, I will actually, like I said before, I'll literally go to detox documentation. You have a link to it in your chitchat. I will go to actions and since I want to tap, I will find the tap action in here and you can see there are working examples, so you can copy paste. So I was just copied this line. I await element by the tappable tap and I will just paste it into my test like this. And the next thing that I will need to replace is it will be my test ID. So for now, let's just put the test ID that I have. I will explain how to find it or why this test ID. Later on, we don't need to focus on it right now. So just do it like me. So you will add this line into your test and then I will add my test ID and you will do the same. So take your minute and add this expect line element by tappable tap. You can also copy it from Docs and give me reaction once you've added it. And I will search for the exact test ID while you're waiting. Are we good here? Have you added this line or you found it? Is it up? Let me know please.
Okay, I see, cool. Okay, so the thing we need to update in this test. Also, I will give you more time once I will complete this test. So you will also do it and run it. So what we will need also to add it in here. So just put the same ideas that I have right now. Don't really pay attention to why it is like that. And I will explain after we're on our test, like why do we need this ID and how to create it. And I will, since my text that I'm looking for is button pressed, I'll also replace this by text with button, okay, okay, mm-hmm, okay, save, and I will run my test. So take your minute, do the same. It stays on the screen. So just do the same thing. Okay, I think you'll have your first failure here. Yeah, I might. Yeah. Cool. So it's, okay, yeah, it's fine. It's on purpose failure, so we're good. We will actually do everything through fail and fix so you'll learn some better practices and everything and such. And just give them a reaction once you're done with it. And we will fix the test. We'll do the green, and then we'll switch to another exercise. Okay. I love that we have so attentive participants. Okay, cool. So we have our first test and it's actually doing the same that we need it to. But currently it fails for the reason it cannot find the measure that we're looking for. So in this case, I just had a wrong text written. And that's the reason my test failed. But you can also have some mistake in your test ID or something and this case, it's like pretty clear it will fail. So in case I will actually replace it like this, it should already pass. Fix it in the code. Yeah, fix it in the code. So it's actually a good thing sometimes when your test fails and you actually wrote something meaningful, you wrote the correct text in like your logic, but test failed, sometimes it really means that you need to update some text in your app because it doesn't make sense. So my test is green now, it's working. Please, whoever is doing this, give me a reaction that your tests are also green now and I will continue to more interesting part, because it's like for now, it's super basic, basic thing.
Okay, cool. So basically, what we do here, we tap on some button and we expect some text to be visible. And we are waiting here element, we're tapping on the element by ID. So what does this ID actually mean? So the best best practice in writing Dtox tests is always match your element by the test ID prop. You can have actually many different options like what to match by, you can match by text, like we did with the test strings we are looking for in Alert. We can match by label, we can match by traits for iOS, and that has some specific ancestor or descendant, we can match with some like combination of measures like element to have this ID and this text, and also we can match at index. We can have many different complicated measures, but test ID will be always the best option.
11. Using Test IDs for Unique Element Identification
To make your test IDs unique, add them to your React Native components. They transform into accessibility identifiers in iOS and tags in Android. You can find test IDs in Xcode's accessibility section and in Android Studio's layout inspector. This is useful for complex projects when you can't remember the test ID structure. Test IDs have already been added to this project.
So with test ID, you can do some tricks to make it super unique and work with it always. So we really highly recommend to add test ID to your React Native component, and only like once you do it, match by your test ID. So in reality, once you are passing your test ID prop into your React Native component, eventually it kind of transforms into the accessibility identifier in iOS and into tag in Android. So in case you're gonna be looking for the test ID, eventually, you can open Xcode. I will like show you before the break how to do it because I think it's like, it's optional thing. You can do it like this, but we will use the prepared the test IDs before the workshop. So we won't spend time on it, but basically in Xcode, if you were to debug your kara key, you can find this accessibility section in here and you see identifier, which is our button ID that we've just used. And in Android, it's a bit different. It's called tag. You can find in the list of the attributes the same way also like an Android you can use Android studio, attach your layout inspector to the hierarchy that you have, to the screens that you have and see tech this way. So why will you need this way of searching for test ID is when you have a super complicated structure of your project and you really couldn't remember how you designed your test ID and you can't get the final version. So in this case you'll need it. But I've already added test IDs to this project. So just, we will just use it as is. So either if you want, you can just search through this components and find the test IDs that you need or you can use mine together with, cool.
12. Tapping on Trendy Movies Image
Let's move on to test writing. We'll focus on tapping on the trendy movies image and expecting the overview text to be shown. We'll practice different actions and expectations. Let's rename the test and copy it to create a second one. We'll use test IDs to identify the image. Run the test to see if it fails.
So it was all the boring stuff for today. Let's switch to test writing. Cool, so let's do something else. We have this second section, which is called trendy movies and it has like a slider with this different movies shown. And it's kinda the same image and title component repetitive. So there are like many of those, we can swipe them and see whatever else we have.
So what I want to do is I actually want to tap on this trendy movies image and expect this overview text to be shown. So we started with just practicing two different actions and further on we'll also practice the better expectations. So let's rename, this test to should tap on button and let's copy it to do the second one. So I want to tap on this image. I will go to this movies gallery and see what is my test ID. So in this case, I have a test ID in here. So it is passed as a prop like so in case you are adding test ID to your React Native component, it might not be supported, so you will need to pass it as prop down and down and down to your actual Native component like tool. Like here I have image. So basically, that's why I'm passing it like here, like props test ID dot image. So my final eventual test ID will be containing two things. It will contain this test ID trendy movies and it will have dot image. So my test ID will be dot image like this. And I want to tap on it and make sure that my overview will be actually shown. And let's shut up on image. And let's, like take your minute, do the same thing, and let's run our test to see that it actually fails and then we'll figure out why.
13. Tapping on Image by Index
In Detox, it's important to make your test IDs unique to avoid tapping on multiple elements. The best practice is to generate an index for each image in a repetitive component. Another option is to use the 'at index' measure, which allows you to specify the index of the image you want to tap on. Make sure to check the documentation for the correct syntax. Let's run the test and see if it passes.
Okay, cool, so I hope you are done with this test. And now let me just explain what is the reason for this thing. So once comparing to web automation, once you are searching for some element, like you want to tap on some image that is repetitive, or you have some list component and you have titles that are repetitive. And they have actually the same test ID. So in my case, all these images, this one and this one and this one and this one, all of them have the same test ID because it's a repetitive component. So if you're working with web automation, most cases what this test would do, it would actually tap on the first one found. But DDoS doesn't work like that, it will actually fail with the issue that multiple elements were found by this measure, which is actually good for your testability because in this case you will pay attention and you'll need to replace this measure to be super unique to tap on a specific one. And in this case like I did it, it's like super generic and it could tap on actually any image. And in order for this to pass, I will need to specify what is a specific image I want to tap on. So again, the best practice is always to make your test ID unique. So what you can do with it, you could have actually in this component, Movies gallery, what you could do, you could somehow here generate your index of the image. So you would have your test ID like dot zero, you would have the index of the image that you want to tap on. So every image would have a unique test ID, like the first one would have zero, the second would have one and blah, blah, blah. So this is the best practice, but it would be too easy if we had only best practices. So let's do this another way. I will just remove it. And we will use another option that we have. We have a measure called at index. Again, I'll go back to documentation to show it to you. We have measure called at index. And I'm showing you the documentation always because depending on the measures that you use, sometimes you will have different like structure of this line. So pay attention to all this like parts where you're placing it. So I will just copy this at index and I will just put it right in here before the top. And I will tap on zero image, which is the first image in my line. So the Shawshank movie, and I will expect for it to happen. And let's run it to see it is green. Take your minute, do the same, make sure that your test is green. I hope my test will be green actually. Yes, cool. Okay, cool. Give me reactions once you are done with it. Cool, cool. I see reactions. Awesome. Great.
14. Tapping on Image and Swipe Action
We specified the index we want to tap on and reloaded the state before starting the test. However, when we tried to tap on a movie image, it was not visible enough for Detox to tap on it. To fix this, we need to perform a swipe or scroll action before tapping on the image. I will demonstrate this in the next test. Run your test and let me know if it passes.
Okay. So now let me explain a bit what just happened. So we specified, I think you get that we specified the index we want to tap on. So I will actually in a branch with test. What you will see is you will have the old test examples. You will have failure results and the reason for failure and the green ones. So you can catch up on that afterwards but I will keep only green test. So our best suite will be green. So what you see in my test is that it was actually reloading the state before it started. So that's why my test, I have two tests now. Every test started from the same starting point from the home screen. And in case, I would remove this line. It would actually, the second test would actually start from this scene. We'll play with it a bit in the flackiness part but still just FYI, we really need it once we have multiple tests.
Great, so we are good with a top on image by index. And the next thing that we will actually do, I want to top on an image that is, let's say certainly in the line. So this one, let's say the Godfather. Also movie, so let's try to top on it. So I will again, copy my test. I should top on third image by index, and I will replace it to top at index two. And run my test. Take your minute, do the same, and let's see what happens. Okay, cool. We have our failure. So give me a reaction once you also have a failure so I can start explaining it. And I'll probably skip the previous test that I had so it will be just faster. Okay. And waiting for your reactions. I see, okay. Give me a few more, and I will proceed. Okay, awesome. So we have our failure. Awesome, cool. So what actually happened in this case? What we tried to do is we try to tap on this movie, which is kind of possible if I do it like manually. But the reason for the failure in this case would be that our image we were trying to tap on was not actually visible enough for the Detox to tap on it. This is an important thing just to know that in case you are trying to tap on an element that is not passing a visibility threshold you can see an issue in here. It can be 75% or 100% depending on the type of the component that you have. But in case it's not passing it, it will fail on this step just because it couldn't tap on it. So in order to actually fix this thing, what we'll need to do is we will need to do some swiping or scrolling action. And after that, we will tap on the image that is shown. So since this one failed, let's just rename it to shooter scroll, sorry, swipe. And tap on third image by index. And again, we will just go to our documentation in here, we will find action that we need, which is a swipe. And I will again just copy this first line. Sorry, scroll. I need a swipe. Okay, now let's swipe, okay. Oh like this, yeah. Great. So I will paste it before tapping. And what I will need to replace, I will need to replace the component I am swiping at, so where I started the swipe action, and then the direction that I'm using for the swipe. So my direction is definitely left. And the component that I will be swiping is actually my image that I have. So the better practice in case you're swiping something, will be actually to start swiping from the first component that you have. So your swipe will be kind of like the smallest, and kind of controllable. So it's like a little hint. So in case you're doing this, I will be swiping from, like, like this. Let me copy all of it. Okay, like this. And I will just paste it in here. So I will start swiping at zero. I swipe left, then I try to tap, and then I expect, again, for this page to be open and everything to be visible. And I'm trying to run my test. Take your minute, do the same. I'll leave it like this, so you will see the code. But I really encourage you to copy paste from documentation. It's actually the easiest and the fastest always. So, just do it. Cool. My test is green, let me know if your this is green also.
15. Exploring Swiping and Scrolling in Detox Tests
In this part, we discuss the issue of swiping in Detox tests and its limitations. We explore an alternative option, scrolling, which provides more control and stability. Scroll has various options, including scrolling by a specific element and continuously scrolling until an element is visible. We recommend using the 'while element' command to wait for an element to be visible while scrolling. This provides a more reliable approach for interacting with elements below the viewport.
And guys, there is no rush, so in case you need more time, you're always welcome to text me in chat. If you need another minute, just feel free. I want everybody to complete it. Mm-hmm. Okay, I'll wait for two more minutes because I see not a lot of reactions. So just do it and we'll continue from that point.
Actually, I noticed that if you swipe not from the first image but from the entire trending movie section, the swipe is huge and you go a lot past the Godfather movie, and the test fails. If you are waiting for us to finish, you can always play with swiping in different components, swiping in different indexes, and giving more attributes to the swipe, like the speed of the swipe inside. However, swipe is not so controllable, and it may work differently depending on the simulator and the size of the screen. I will show you another option that you can use in such cases, which will be a lot more reliable.
Another thing we can do is to scroll. Scroll has many different options, such as scrolling by a specific element, scrolling in a specific direction, and scrolling a specific amount of space. Another option is to scroll continuously until some element is shown. This is the most stable way to tap on or wait for an element that is below the viewport. I recommend using this while element. It waits for some element to be visible while scrolling a specific element by ID. Make sure you have a scroll view to actually scroll it.
16. Scrolling and Checking Element Visibility
Scrolling in Detox tests has various options, including scrolling by a specific element, scrolling continuously until an element is visible, and scrolling up or down. It is recommended to use the 'while element' command to wait for an element to be visible while scrolling. In this exercise, we will create a test that scrolls to the 'other movies' section and checks if it is visible. To do this, we will replace the element we are scrolling and the element we are expecting. Make sure to add a test ID to the scroll view in the Home.js file. Take your time to complete the exercise and run your test to see the result. Feel free to explore other scroll options in the Detox documentation and try using scroll instead of swipe in appropriate cases.
You can play with it also on your applications. And another thing that we have other than swipe is also to scroll. So scroll has actually many different options. First of all, you can just scroll by some specific element like at specific direction, at specific amount of space scrolled. And another option, what you can do is you can scroll continuously until some element will be shown. So basically this is what we will try because I believe this is the most stable way in case you are willing to tap on some component or at least wait for it to visible and it's like below the viewport.
So I would recommend using this while element. So this is a pretty long command. What it actually does, it waits for some element to be visible while element by ID will be scrolled. So make sure that once you will be scrolling you are scrolling your scroll view. So you should have a scroll view to actually scroll it, which makes perfect sense. So what we will be doing is let's just go in here, create another test for us. Okay. And what we will do is we will actually call it should scroll until some element is visible. And then we will top on it again. Or maybe let's just wait for something to be visible to see it and to make the text. So I want to scroll down here and actually see this section. So I want to check the style other movies is actually shown. So pay attention that it's like a repetitive component again. So we have the training movie section and then we have other movies, which is the same section but with a different name. So again, a repetitive component. So you need to be pretty careful in terms of like the test ID, again. So let's just try. I will actually show you the command of scrolling and then I'll give you a space to try it on your own to find the exact measure that you need to find these other movies text and not the one in the bottom. Cool, so I will just remove these two and go to the documentation. I will copy this long command, this one. Wait for a while element and I will put it into the first line. So now I will need to replace the element I am scrolling and the element that I'm expecting. So make sure that first element is the one you expect and the second element is that you scroll. So I am expecting, let's do it like in a stupid way. I will do other movies text, so we'll wait for text. No need for a complicated measure just to see test screen. And then I need to scroll by some scroll view, so it's a homepage. So I'll just check and go if I have the test ID actually, which I don't have. So what we'll do, we'll actually add it right now. I will add it in here and I will call it HomeScrollView like this, like this. And I will put it in here and I'll just remove the second line, recommand the second line for now and just execute the first one. So again, take your minute now, copy this long command, then replace the text you are matching by and add a test ID to your home. I'll leave it like this, so you'll see where to put it. Just add a test ID HomeScrollView which you will be scrolling by. So take your minutes, one, two, five, it's okay. Just try to do it. And I will open the test in there like this. Sorry, just a sec, like this. So you will see both the test and the home. Yes, do it and give me reactions that you're done. And run your test actually to see that it is green and see what it is doing. And I will show it in my machine afterwards. Just checking where we supposed to add the test ID to our scroll view or not yet? So yes, feel free to add. You go to this Home Js file. Then you have this scroll view, which is like for the whole page. And you are the test ID right at this, just like this. You can add your own test it is that you like and just put it in there. And always remember the best practice to make it unique so it won't mess with some other scroll view in case you have it in your page. Guys, four more minutes to complete it. Take your time and give me reactions once you're done. I see one reaction already, super cool. But a few more minutes for everyone to continue. And guys who've just finished, I highly recommend you to go to the documentation and play with other options of the scroll. Play with the scroll down, play with the quick or I see more reactions. Play with the scroll to the bottom, play with this scroll like this one. There is scrolling just up or down, scroll to edge, just play with the API once you have time. And you can rewrite the previous example where you were using swipe instead of slide. You can use a scroll too, right? It can be more stable. But swipe sometimes is the option, but I would say swipe is more the option in case you're having some slider component that always slides to only one, to the second one, the first component that we have in here. Like this one, that can change to only the second image, so swipe would work there. But in other cases, it's better to make sure that you're looking for something specific. Okay, good. I see. Okay.
17. Adding Expectations and Unique Matchers
Uncomment the expectation and use the 'to have text' matcher to check that an element has the exact text. It's best practice to match by ID to check element visibility. Make the matcher unique by modifying the movies gallery or using other matchers like end or ascendent. Test the modified code and let me know if it's green. Having multiple expectations in one test case is acceptable as long as they check different criteria. However, if the first expectation fails, the others won't be executed.
Cool. So let's do it one more minute and we will continue to the next one.
Okay, few more seconds and let's continue you to the next part.
Okay, so I'll close this HomeJS. I think most of the people are ready done with it. So the next thing that we will actually do, like what we did in this test, we were actually scrolling down until some element will be visible. But this is not really a test. It actually does some action and scrolls and not fails, but it's not actually a test. And the reason for that it's missing an expectation. So let's now uncomment this expectation and let's do better expectations that we did before. So what we did before in most cases is we did expecting by the text. But expecting by the text is not always a best practice. And the reason for that is we actually can change the text. We can have a multi-lingual up, which means the text can be different depending on the language and more. So it creates flakiness and extra maintenance costs, so we won't need it. So the best practice always is to match by ID if you want to check that the element is visible. But if we want to check that the element has the exact text, what we need to do is we need to wait, like expect some element by ID to have specific text. So this is what we'll actually do. I will show you also the expectations docs. So we can expect to have different things. We did before the expectation to be visible and we can have also to exist, to be focused, to have text and such. And you can also add a note statement this one, in case you want to expect some element, not to be visible. So you just add it like this. You add, expect element blah, blah, blah, dot not, dot to be visible. So it just works with any expectation, but I will use a different one I'll use to have text. So let's copy it. And what we will do in this test is I want to expect that element by ID has text, other movies. It's a little bit stupid in this case because we're actually scrolling to see other movies and then we do it, but still. Let's do it. So we'll just try this API. So I'm gonna be checking that my component, my title, that I'm looking for having the correct text. I will go to my movies gallery to get the test ID of my title. I think it also doesn't have it. So let's just edit in here. Here. Cool. So I will just again add my test ID. I will call it, let's do something super stupid right now, which we'll need to fix eventually. Let's do a generic title called title, which is like never do the same, but let's do it just for the experiment. And let's call it title. And let's just edit into our test and do expect element by ID title to have text other movies and save. And let's just run our test again to see what will we have. Again, I'm opening it like into parts so you can see both, add your test ID, add this expect element by ID title to have text other movies. And let me know if your test is green or not, just give me a reaction. I think there is some reaction that Yaroslav is always using with the green apple. So in case your test is green, just give me a green apple if you have it in your reactions. And if it's red, give me something else. And I will actually run it also. Red, okay. Let's see what we get in here. Okay, I also have red, cool. Who else has the red result? Okay, cool. Okay, anybody else? Okay, red tomato, very original Yugoslav. It's very original. Okay, red, cool, great. So you can continue writing tests after me once I will be talking. So I think you already get the reason of the failure. And the reason of the failure is actually that our mixture is not unique, it was like extremely generic. So let's do another trick to actually make this mixture super unique. So I'll do a little challenge for you. So go into the details documentation actually, and try to make this matcher title, try to make it unique with any possible ways that you find. You can either modify this, like in movies gallery, or you can do it through the actual matchers that you can do like you can use end matcher, you can use ascendent or anything else, and just do it, make your tests green, like a little challenge task, and give me reaction once your test is green, and eventually I'll just show you one simple, like multiple ways to do it. So there was a cool question about, should we have multiple expect in one test case or not? So it's a good question because it really depends on the case. So in general, I would say that it is best to have your test checking only one thing. It doesn't mean that you have only one expectation, but it means that your test goal is to check only one specific thing, that some action happened or I don't know that account was created, and blah-blah-blah. And once you are checking it, you can actually have multiple criterias on how you check. For instance, if you did a successful signup, when you have some success message, and you have an account image appeared, like in reality, manual QA would do multiple checks. He would check that success message is correct, he would check that image is appearing, he would check the name is appearing and such. So in this case, if you're kind of expecting multiple elements, it might be okay, but you need to know the downside of it is that in case this first expectation fails, the other ones won't be executed. So in this case, you kind of suffer not checking two more expectations, but for this specific case, it's kind of fine.
18. Best Practices in Test Writing with Detox
When writing tests with Detox, it is important to avoid combining multiple steps and expectations into a single test. Instead, split the tests to check each step individually or use different levels of tests. Detox provides multiple options for matching elements, including generating test IDs for repetitive components and using ancestor or and matchers. It is recommended to make test IDs unique and modify component code when possible. Detox also allows for platform-specific code execution, making tests generic for both iOS and Android platforms. Take a minute to complete the test writing exercise, and let me know when you're done.
But in case you are doing, what like definitely you should not do is when you do step, step, step, expect, then two more steps again expectation, this is not the way to go. You should split those tests to check the exact same. So even if you have something like you are doing the signup and let's say you are entering your data and then you press the button and then you want to check, let's say that your button became active, then you press it and you want to check that your account was created, it's not the best approach. It's better either to replace it with two different tests or in this case, I would better replace it with different levels of tests. Like checking button disabled, enabled, I would check it with other levels, probably like component tests or something like this. And the actual scenario like of the signup, for instance, I would check with the complete end-to-end test So again, like use it wisely, try to use one expectation, but in case you want to check for multiple like situations to appear in the same point, you can use multiple. I hope it answers the question.
Cool, so there are actually multiple possible options that you could have used. You could have actually go to this test writing chitchat in here and see, like this. Okay, so you can see here multiple different options. So you can either generate your test ID for such repetitive components. So you might have added something like, instead of having here, just the test ID title, you could have passed the props test ID dot title, and in this case use it. Another option which you could use is to use these two options, either with ANCESTOR or and matcher. So with ANCESTOR means that your ANCESTOR component, like this one, for instance, should have some specific test ID. So in our case, the easiest without even changing the component code is to actually say with ANCESTOR other movies, because my ANCESTOR has like other movies ID and it would work. So if I do, I will just copy my line completely so I won't spend time on that because we have more things to do. So I would do it like this, if I don't want to change the component code, I would do it like this and it should work. Let's try to run it and see it. But of course it's not the best practice. I'm showing this ANCESTOR, descendants, indexes and everything just for cases when you cannot really modify stuff or you're like importing some component. In this case you can use, and just to play with Dedux API also. But in case you are, you can actually make your test IDs unique, then go with it. Cool, our test is green, which is great. So now I wanted to show you one last thing actually to play with. Is I wanted to show you how to add a platform specific code. So I will just copy my first test. And just, it will be like, just to show the concept. We won't write any complicated code. So it's an easy thing to do. I will call it should have platform-specific code. And I will just modify this test to execute the platform specific code. Let's say, I will do, it's actually an easy thing. I will just do if device.getplatform. So if device.getplatform equals iOS, then in this case I will do something. And I can have the same code for happening for Android. And, basically, it means that, in case you're running on iOS platform, I think you all get how it works. It just will go into this one and execute this line, and will ignore lines that are in Android. This is a really good way to making your tests generic for both platforms, in case you want to use some platform-specific actions like you had as, like you've seen on the actions. So let's actually try to see if it actually works. So, I've put this top on yellow button from the first test into the iOS, so it should be executed on my iOS run. And then a test should be green. But in case I will put it into Android, it should be ignored and test should fail because there is no such thing. So let's just do two tests like this. So we'll test it. Just watch after me now. And then you will try the same. Like this. And I will put this one into the iOS, and I will run both on iOS. Okay. Cool. We should have two tests. Okay. So first one worked because it actually was the iOS platform. And the second failed because it ignored the code that was in the Android part. So again, one last test writing exercise. Take your minute, do the same, and then I will show you stuff related to test running. I just believe that this thing, like while I worked was also, like I worked with different frameworks, like hybrid frameworks for mobile automation before. And with Detox, I believe this is a really cool way to make your tests generic because I like, I think that many people like to reuse code as much as possible. So I would go with this in case you're making generic. And again, give me reaction once your tests are good. One should be green, another should be red. So Yaroslav, the perfect emoji for this would be a traffic light probably. Okay, I see reactions. Great, let's do one more minute and we will finally switch to debug in a failed test. Okay. Okay. Cool, so, I think I will continue from this point. I'll just remove these test I have and I will skip all my tests because we will switch to test writing part and we will be playing a bit with the failed tests. So this is what we'll actually start with. So, in Detox you have many, many tests and in Detox you have many, many different options while you're running your test.
19. Investigating Test Failures with Detox
Open the test writing cheat sheet and scroll down to the failed test section. Learn about the options available for running tests in Detox, such as specifying configurations, device names, and log levels. Try running tests with different log levels to get more detailed information about the interactions with your application. Use the Detox API to take screenshots of failing tests and access them in the artifacts folder. Record videos of failing tests using the 'record videos' command and find them in the artifacts folder. These features are helpful for debugging and analyzing test failures.
Please open the test writing cheat sheet that you have. Again, and find like scroll down, find the failed test section. So, usually when we are like thinking how we want to run our test, so you just go to Detox documentation, to the Detox CLI and you can actually see what are the options that you have for the test. So for test, you can specify the configuration you run with like we did before. You can do the run our config in case you have multiple configs at your project. You can specify the device name like if you want to run a specific. You can also work with low levels if you will try which is helpful for debugging. You can use test artifacts. If you want to try it, we'll also try it in a few seconds which is like screenshots and videos which is my most lovable tool in Detox because it really helps you to debug your tests super fast, and you can also specify some retries, cleanup after your tests. You can specify workers to run in parallel and we will try all of that right now. So no more talking from my side. Just playing with it. So let's try the first thing. Let's have some tests failing. Let's make it this second test you remember that was tapping on Image by Index. And let's leave this line as is and let's just change text in Overview to OverviewblahBlah. So this test should fail and then skip it and just run to see that it fails. So I just want to see the red test and start doing something with the redness. Just let's wait for it to fail. Okay, it's happening here. Yes, so it failed. So let's say we want to know what is the reason for this failure. We want to go into detail. So the first thing in these that you can do is you can run with a different log level. So you have many options. I recommend using verbose. So just let's do it right now. Add to your running command minus L and put verbose in here. And run with it. Take your minutes, do the same and check what you will see in your logs happening. You will see the exact interactions with your application happening. So you'll see a lot more information about it. Cool, so actually, like Amit texted in the chat, the default log level is info. So we can go deeper with the verbose and you can actually see the things that you had in your screen and it's like super long but it's like really informative in case you're looking for an issue and you're not sure what it is. In our case, it's pretty clear but still, in case you're not sure, just try using this log level. Let's try the second thing. Let's try actually to take screenshots of our failure. So Ddocs has an API that does take screenshots for your test depending on the prompt that you give, it can either screenshot all your tests, it can screenshot specific tests, it can screenshot only failing or none. So I will screenshot the failing test that I have. Let's just check that my command is correct. Yes, it is, cool. So again, take your minute, run the same and I will explain what just happened and where to search for those screenshots. Okay. Okay, so my test failed, I've got the screenshots. So give me reactions once you're done with it so I can start showing and talking about the screenshots please and everything. Okay, cool. I see many reactions, great. So you can see on the left, maybe you noticed it already that you have here an artifacts folder created. And this artifacts folder, what does it have? It actually has the three screenshots. So first screenshot it has is on the test started. So the way test look once it started. Second screenshot that you'll see is on the failure. So this is an exact point of your test when it failed and then you have the test done, which is the last point after all the final cleanups or like after code executed. So this is the final one, which you will see in my case, since I'm not executing anything after my test, it will be just the same, but basically you're having three screenshots. So you can check if you are missing anything on your screen, like if you're waiting for some element and you're actually missing it or something else. You see that like in web, it's really popular to get such like failure because something was not yet loaded on the screen, but here we don't face this issue because even though we have multiple loaders in our app, Dtox waits for it to go idle, and only then it waits or it like checks for something to be visible, so we won't need those waiters to add, we don't need like to do some custom waiters for animation and such. It does it automatically. So, this is like the screenshot stuff, I really love it, it's like super useful if you're working with your own project you can play with it also, and once you are setting up Dtox for CI, which is kinda a point for different workshop, but still, in that case you will be also, like you can do some magic, you know, upload your screenshots somewhere and just access them from there or you can like actually use this screenshot API anywhere you want. Cool, and the next thing that we will actually try, the last thing in like investigating the failure is to know why our test failed by the video. So, let's try to use record videos command. It's almost the same like the take screenshots, but you just add here record videos and you put on failing and you run it and again, do it, see what happens. Try to find your video. It will be in the same artifacts folder and give me some reaction. Oh, okay. Okay, are we good? Have you found the video recorded? Okay, I see one reaction. Okay, cool, I see two. Cool. Okay. So, for every run, you will have this folder created with the exact date and time of running, so you can find your exact run. And here you will have your video of the test file.
20. Debugging Test Failures with Detox
You can use the full video of the test to debug your test failure and see the steps. Detox provides a test artifact that is usually enough to debug your specific test. It's one of the most lovable features of Detox.
I'll just reveal it in my Finder, and let's just open it to see what was happening. So this is the exact test. It actually topped, and then it failed. So let's replay it. So this is the full video, and this is probably the best tool in case of debugging your test failure. You can see the full test steps and see what was happening. So this is actually almost the last thing for debugging a failure, because usually those stuff are more than enough. But in case you want to debug your step-by-step like you usually do for your application, you can also use a regular InSpec breakpoint flag in your test command, the same test command, then you go to from InSpec. It's always attached... Like you do it for your regular app, you can debug it the same way in case you need it, but in most cases to debug your specific test, this test artifact will be enough. And it's actually like one of the most lovable features I believe that Detox has. Cool. All the features are of course lovable, but this one is my favorite.
21. Viewing Test IDs and Running Tests in Parallel
In this part, we learn how to view test IDs in Xcode and Android Studio. The speaker explains two methods: adding a line of code to create a snapshot of the hierarchy or attaching to the process in the device. They demonstrate the process in Xcode and mention that it can be done in a similar way in Android Studio. The speaker emphasizes the importance of designing tests to run independently and provides instructions for running tests in parallel with multiple workers. They demonstrate the process and highlight the significant reduction in test execution time. The speaker concludes by mentioning that they will share tips for dealing with flakiness and invite questions from the audience.
Okay, cool. So now I wanted to show you one more thing. So sometimes another point pain in the ass or reasons for failure can be the test IDs that you added your destined which was eventually incorrect. So like I promised, I will just show how you can see your exact test studios. So I'll show it in Xcode and then I'll try also to show it in Android Studio. It's a bit lags for me, so I might show it on the here, but even in case I won't show it for Android Studio, I'll give you instruction how to do it on your side because it's like the same logic. So basically in Xcode, what you need to do, you just open any project, like I'm not actually working with Xcode or Android Studio while working with Detox because Common Line is more than enough but in case you want to visually see the hierarchy, you can do it in two ways. You can either add one line in your test in the end that will make a snapshot of your hierarchy and you can just open this file or you can actually attach to the process that you have in your device in here and in this case, you will be able to just attach to this one. So I will use debug, attach to process. I'm getting the list of process and this is the one that I need. So I will just wait for this to happen. Like you can rest now, there will be no coding after this place so you can rest. That was the last point of coding and or you like if you're interested in parallel with me talking you can always play with other APIs. So you need to open if you'll be doing this you'll need to be opening this detox workshop detox workshop and find up delegate file, open it and then you see in the bottom in here it's a bit hard to show you, I cannot enlarge it but you see there is a debug you herarchy in the bottom. So if you press it, what you will see is that my actual hierarchy will be shown. So behind the xcode you can see that there is another device that was actually open it's like for attaching to this process so you can ignore it. But my actual UI from this place is shown in here, and if I tap on any element, you will see that on the right side I actually have the accessibility identifier, this one, which is my actual test ID that I was passing. So in some cases, if you haven't passed it correctly to the like down and down and down to your actual component like native component in this case, you might have it like empty, or if you did some, you know, confinemation and you added some lines you might have it just in the wrong way. So to just check yourself, you can go here and see like what are the accessibility identifiers that you have? So you can see in here like in this mode and you can also switch in here to the 3D mode. You can like see the exact hierarchy that you have. You can find like ancestor or descendant components to like use. And you can see here that I have this Tranding Movies image that we've used before. And this one will be Trending Movies title. So you can actually work with this part while copy pasting the test studies in case your project structure is like really complicated or something. Cool. I lied. We have one more thing actually super cool thing to try. I totally forgot about it, but we will do it definitely. I think you'll love it because we will try to run in parallel. We will actually doing super easy tweak. We will just duplicate our test file. This one we will just copy it and rename it to be second test. So let's just try it. Yes, and let's have some, remove most of my tests to just have only one test with the scroll, which is pretty long in the second and some short test in first. Let's let it be this first test. Okay, great. Now I have two files where I have test. So in order to run in parallel, what you need to have, you need to have two separate files with test. So each of the files will be open in Trell. So in order to run in parallel, you basically use this minus V workers flag which specifies the amount of workers to create for you. I will create two you can create more up to you, but you always should remember that it will be like a tip. I really love to say that once you're designing like writing your test, you should always write it just like it will eventually run in parallel with other tests, because once you are designing your test super independent, so it can actually run and don't fail other tests and don't interact with other tests and actually run independently isolated mode, in this case your test will be the best. If you're in test dependent, it will always be a problem eventually. So, let's just run it in multiple workers, I will do two, I will do minus V two. And first run will be pretty slow because my second emulator will be launched. But after that, once I will do it the second time, it will be a lot faster than doing it in one worker. So, let's just try it. Okay, so you see my second emulator is starting and it will take time for it to start. So, in the first one, I just started to work already, I will rerun it afterwards. And now you can do the same, just take your minutes, create the second file. You can even have all the tests in there, just make sure you have two files for some tests and run with this minus v2 and give me a reaction as always. Cool, so my tests are actually done. Give me reactions once you are also done, and meantime I will just rerun my tests. Cool. Let's see, it is done. Cool. And second time, you can see if somebody's watching me now, you can see that it happens a lot faster. So tests are actually running for, and it took for each test a lot less and in total it was by the longest test. It was 15 seconds and not like 40 or 30 seconds that we would have if we would be running sequentially. So if you continue doing this, if you're not done, and I will actually switch to the final part of this workshop today, we're almost done. I want to give you some cool tips about flakiness because in Wix we really, really fight flakiness a lot. We just hate the same, both in web and mobile and we have some kind of tools that we create around it and some tips that we have, so, and I believe that they actually work, so I want to share a few. And if you have any questions, feel free to post them right now to the Zoom chat and we will address them afterwards once we have Q&A, and if there will be no questions, I will give a little word maybe to Amit to give a few insights about what's waiting for us in future in case he wants. And after that I will reduce from this workshop, cool. So I will open this test writing and I want to talk a bit about slackness, so usually when we are talking about add to testing, slackness is something they created by either environment or our hands, meaning when we write, she did us. And I must say that the second part happens a lot more often because sometimes we can write some not unique matches, we can miss some element or we can scroll not consistently. So these are the things that actually create slackness. Another point of creating slackness is actually the data. So imagine you have a test that is doing some changes in their profile of the user. So it changes its name or something like this.
22. Test Isolation and Best Practices
To ensure test isolation, follow a correct test structure with preparation steps, the test itself, and cleanup. Avoid creating dependent tests that rely on specific order. Start each test from a fresh state and match elements by unique generated test IDs. Try running tests in parallel threads to ensure isolation. If flakiness persists, use the 'retries' command to rerun tests multiple times. Detox is open source and welcomes contributions. Thank you for attending the workshop!
And then you have another test that does some opening of the user profile and checking that its name is visible. So in this case, what you will see is that your tests are actually interacting with the same, same data. So the first test will actually pass because it will be changing something, but the second one most likely will fail because it was looking for some old titles that is not actual already. And such situation happens pretty often because we usually test on the same test account and it's not really relevant, you know, to create the test account for every test so you need to think how to make your test isolated.
What works in this case is like, I think the best structure probably, I will stop sharing this thing or so we will see faces of each other. So basically the best practice, I believe is to keep the correct structure of your test in general. Is to have some preparation steps, sometimes it's even better to do it through the API, you know, to create a user or to do some change, and then the exact test will be happening through the UI, like we did it today. And after that, you will have some cleanup phase. Cleanup phase is all, it's also I think better and faster to do it through the API, but even if you can't, you can do it through the UI. But remember that in case you're doing that cleanups for your UI, if your test fails, then your cleanup will also happen because this will be an after this. So you can have some mess happening with the data. So I'm still a fan of having some API data setup then the test itself, and then the cleanup. Make sure that you don't create tests that are like, add the contact and the second test that is deleting the contact. It is not isolated, it's not consistent because if you replace the order of those tests, they will definitely fail. And it's like the biggest tip probably is not to create dependent tests. And a few more is once you are starting your test, make sure you started from fresh. Like we did reload React Native before every test that you have, do it in before each statement. So you will have those, you actually have those tips in the chitchat so you can go through them afterward. So make sure you start from fresh. Match by something unique like we did today. Again, summary, like summing it up, it's always better to match by some generated test ID that is like unique to the component other than doing some tricks on the APIs or doing some tricks around super generic test ideas. Use this correct test structure and try to run tests as they would run in parallel. So you can even try, like we do it sometimes for a web. It's a bit heavy for mobile, but you can also try it. What we can do is you can put your tests that you are willing, like new tests that you created and you're willing to push, you can put them in separate files and actually run them in multiple parallel threads, which will actually give you the real picture in case you would be running them not isolated. Because in real life, what can happen in case you're interacting with the same data, you can even run in one thread always. You can have no parallel execution. but you can have multiple PRs happening in parallel from different people and you'll still have interactions with the same data. In this case, it's just like a tip, try to run your tests in parallel with themselves to see that they're isolated and you will be good. And another last point that I wanted to mention, we have a cheating command, let's call it, which is called reuse. So in case you did everything that you could and you couldn't actually fix your flakiness, sometimes it happens. We get it. So in this case, you can run with a flag called retries x, like retries three times, which will actually retry your test, like rerun your test up to three times to see if it passes. So in this case, your test can pass from the second try or from the third try, which is not a good thing to do. But in case you don't have other options and you want to make your build green, do it. So this is actually it from what I wanted to say for today. I will share my screen to show a beautiful slide in here. What we did today is we actually tried to... We learned how detox test look like, we learned how to find an element, we tried different measures, actions, and expectations. We tried how to work with platform-specific actions. We also tried the Detox CLI in action. We used different log levels. We tried to record screenshots and videos of our tests. We actually ran in parallel and we learned some flakiness tips. So guys, we did a lot. It was a long two hours and a half and we have some time for questions. Also I hope you have some. And I wanted to, before we switched the questions, just to say that Detox was an open source from the first commit and TDD project from the first commit. So if you're interested to help us out to develop some feature or to fix some bugs that you see, or actually to become part of our team, you're always welcome. So you're super welcome to contribute. You need to search in our project for tickets called user looking for contributors for this label. And we also have a Detox contribution guide you can find by link. I will share the slides in the channel for the workshop right after and all the like information and you're welcome to ask anything afterwards until this channel will be deleted actually. And now I'm done talking.
Comments