 Hello everyone. Good afternoon. Welcome to the next session on how to develop Selenium tests using JUnit 5. And for this we have Bonnie with us. Welcome Bonnie to Selenium Conf 2020. Lastly, thanks to BrowserStack for sponsoring this session. And Bonnie without further ado, the floor is yours to take it from. Well, thank you everybody for joining me today. I'm going to present a workshop, a small workshop, and I did developing the unit 5 tests with Selenium. This is my slides. They are available on my slideshow. So, well, basically what I'm trying to explain today is a tool. Okay, I'm going to explain a tool I have created to create as the title suggests how to create Selenium tests with JUnit 5. And we can see in this slide that of course Selenium and JUnit 5 are the most important technology for this technology, but also Docker. I think I suppose many of you have heard about Docker and probably some of you use Docker. These three technology and the main building blocks of what I call Selenium Jupiter. Okay, Selenium Jupiter is what I'm presenting today. It's a JUnit 5 extension for creating Selenium tests. So, basically all that I am explaining today is open source. The tool, Selenium Jupiter, of course, is open source. The documentation is available. And what we are going to do today is to run different examples which are available in this URL. Okay, this repository I recommend you to clone or fork in order to follow the examples because the funny part of this workshop is to touch the technology. Okay, so if you click on this URL, you can go to the samples. And the presentation is divided basically in two parts. First, I'm going to explain a bit more important. This is about JUnit 5. Very briefly because we don't have much time. We have 45 minutes. And then the most important part is about Selenium Jupiter. Okay, how to create these tests, these Selenium tests using the programming model called Jupiter. So, let's get started with JUnit 5. JUnit 5, well, is the last version of the popular testing framework JUnit. Probably you know about it. It was raised three years ago now in 2017. And in that time, I followed the development of the tool very closely because I wrote a book for a pack called Mastering Software Testing with JUnit 5. And in short, JUnit 5, well, is a brand new testing framework which I'm going to present briefly. This is the architecture. We don't have many time to get all the details of the figure because there are many, many details here. But, well, the brief idea of this is that JUnit 5 is a complete new framework. It has nothing to do with JUnit 4. The architecture is brand new. It's completely modular from the scouts. And it has three main components. This big component here is called the platform. And it's intended to run different type of tests in a Java virtual machine, not only JUnit, but any kind of test. It's somehow, well, it's a revolutionary aspect of JUnit 5. It's not only about JUnit, but tests in general. Inside a platform, we execute what they call an engine. Engine is basically a programming model. And out of the box, JUnit 5 provides two engines. One for legacy tests of JUnit, which is the second component of the JUnit 5 architecture. This one, the vintage. I need to execute JUnit 3 and 4. And the most important part for tests and developer is here. It's the Jupyter component. It's the brand new programming model for JUnit 5 tests. And here is the important part for us. Today, we are going to learn how to create these tests. So in order to execute JUnit 5 tests, we have different options. We can use a build tool like Maven or Gradle, typically, also and, but I suppose Maven or Gradle are the most usual build tools. We can use an IDE, like Eclipse, or IntelliJ, or Visual Code, or Netpins. These modern IDs support JUnit 5 of the box. There are three options, which is less important. Here in this presentation today, I am going to use Eclipse. But you at your home can use whatever ID you have, or Maven or Gradle, using the command line. So in order to set up JUnit 5, for example, in a Maven project, we need to copy and paste these lines. Again, I'm going to go deeper in the detail because here it's very interesting why all these lines are in well, as supposed to configure JUnit 5. But basically, I would say that we need the engine of JUnit 5 and also we need to specify a version of the Maven certified plugin, which is supposed to run the test in the Maven lifecycle game. A Gradle is very similar. This is the configuration required to run JUnit 5 in a Gradle project. It's basically the same, but with another syntax. And if we do that, we are able to run JUnit 5 test. And if you are familiar with JUnit 4, well, at JUnit 4 test, we have a class, a Java class in which we annotate the method with an annotation called test. Well, in JUnit 5, it's the same. We have the annotation as the main building blocks to create a test. And in JUnit 5, the names of the main annotation has changed. Basically, the test is the same, the annotation to mark a method as a test to be executed. And what happened before is the before all and before each. And what happened after is the children is the after each and after all. This is somehow the lifecycle of JUnit 5 test. So here is again the same idea. We have a test, which is supposed to exercise and assert assistant under test. And an important part of JUnit 5 test, well, in general, a test is the assertions. We are supposed to verify something about assistant under test. And for that, we need to compare what is coming from the assistant under test, that is the real outcome with something we expect, the expected value. We have a comparator in between, like equals, not equals, whatever. And as a result, we have a veredict. The test passed or the test failed. Well, regarding the assertions, JUnit 5 provides a rich variety of assertions, but we all can also use a library for fluent ascents. Maybe you hear about this hand crest as a date of our trap. In fact, in this workshop, I am going to use trap. Okay? Well, it's a relative new library. It's by Google and it's okay. So in the samples, I'm going to use trap. Well, and JUnit 5 has many, many, many other features. Okay? I recommend you if you are interested to go to the documentation and have a look. There are a bunch of features, but we are not having time to review them. Okay? Last but not least, about JUnit 5, we have an extension model. JUnit 5 provides Jupiter, which is a brand new programming model, but also it's an extension model. And this extension model allows to create new feature on the top of Jupiter. Okay? When I wrote the book, I told you at the beginning in 2017, I realized that this extension model was very convenient for Selenium. Well, because it was very new, what I did is to create a tool which used this extension model, which allows to create Selenium tests with JUnit 5. And this is what I'm going to explain. This is the second part of the talk and it's the most important part because here we are actually going to understand how to create JUnit 5 tests with Selenium using this extension. So what's the motivation to create this tool, the Selenium Jupiter? Well, when I create this this tool, I realize that a JUnit 4 test can be, well, somehow, can be a bit complex because it has a lot of details that makes the test difficult to maintain and led to flaky tests. I will explain this later. But my idea to create this extension is to create clean test code, reduce what we call the bollier plate. I'm going to explain this with code, but which is the way we are going to see this easily. Then, in my opinion, using Docker, it's interesting in very different aspects of software engineering. But in testing, it's very, very interesting. And in web and mobile testing, it's maybe more interesting because using Docker containers, we are going to be able to run different browsers on 100 devices in an effortless manner. So my idea is to integrate Docker in the programming model implemented by Selenium Jupiter. We are going to see this with code. And also, Selenium Jupiter provides advanced features. Well, I have to say that I've been working with testing more than 10 years ago, I did my PhD dissertation focused on software testing with a strong focus on Selenium. And I have some, well, speed is about that. And my effort, I put somehow in this tool. Well, I'm going to explain here some of these advanced features for testing with Selenium. So with all of these ingredients, I have created this tool. I maintain this tool from three years now, I think. And today, we are going to see at least the most important parts, not everything, but at least, I hope, the most important, the most relevant parts. Well, first, to use Selenium Jupiter, we can use, again, maybe an upgrade there, typically. And we need to incorporate these, their coordinates in our project, like this or like this. The last version of Selenium Jupiter at this moment is 335. And now we are going to see the code. This slide basically, what I'm trying to illustrate is that we are going to compare, on one hand, the whole world using the unit 4 and Selenium, which is okay. It's still working. And on the other hand, what is the new primal AI I'm proposing, which is the unit 5 with Selenium Jupiter, this extension. So now we are going to start getting fun, I hope, because we are going to use code, which is funnier than my voice. So here we have the repository I told you before, Selenium Jupiter examples. I hope you can clone or fork. And first, I'm going to show you this. This is basically a Selenium test in a unit 4. This is a unit 4, okay? Notice that we have a test here. Basically, it's a test using Selenium WebDriver to assess the documentation of Selenium Jupiter, open this page and get the title and assert if the title contains that. But in order to do that, if you are familiar with Selenium WebDriver in Java, you know that you need to do this, which is the driver resolution. You need to download the Chrome driver proper for your machine. In this case, it's a Linux machine. Proper for your version of Chrome. In my case, it's Chrome 84 or 85. I think it's 75. And I need to do this manually, okay? This test is not portable anymore. This is in my machine, but probably not in yours. And this is very bad, okay? Because, well, in the long run, this test is going to fail because Chrome is an evergreen browser, meaning it's going to update automatically. And when the browser version changes in the long run, this version of Chrome driver is not going to be compatible. So by definition, this test, this manual test, in the sense that I made the resolution manually, is going to fail, for sure. This test is flaky for definition, okay? So, well, if I run this test, run as the test, the test has passed. We don't see the browser because it's in my other screen, but the test has passed, okay? Well, not with DL so far. So we are going to compare this test with what I proposed today, which is Selenium Jupyter, okay? This is the test. I'm going to move like this, okay? As you can see, the test is exactly the same. The test logic doesn't change, but everything, the recipe code has been reduced dramatically. We're going to review this. First, we are saying that I am using Selenium Jupyter. This annotation is provided by JUnit5, I'm saying this, okay? In this class, I'm going to use the extension Selenium Jupyter, okay, which is in my class path, because I already did with maybe. And then here is an interesting feature of JUnit5. We have dependency injection, okay? We can declare parameters at method level, and these parameters, someone is going to be in charge of instantiation probably these elements. And this element is the extension, okay? Here what is happening is that, well, I declare a variable of the web driver hierarchy, and Selenium Jupyter is in charge of different things. First, internally Selenium Jupyter used another project of mine called WebDriverManager, which do this in an automated manner, okay? The driver resolution is done by WebDriverManager, internally used by Selenium Jupyter, okay? So we don't have to take care about the driver anymore. We only declare which type of driver we want to use. For example, in this case it's ChromeDriver, meaning I'm going to use Chrome to verify a web application using Selenium Jupyter, okay? And also we don't have to take care about the instantiation and the release, okay? What we do here is the proper instantiation and the proper release of this element, meaning close the browser. That's it. Basically, this test is the same, but using Selenium Jupyter, okay? And as a summary, I need only to declare the driver, the variable driver I want to use. Well, if I run this, of course, this is going to, hopefully, it's going to work, okay? But, well, in my opinion, I'm going to back to the slide. In my opinion, the battle between the old world and the new world is for the unit five, and Selenium Jupyter, because it has many, many, many, in my opinion, advantages. So here we can see the valid types for this dependent injection, not only ChromeDriver, but FirefoxDriver, all of these drivers are allowed by Selenium Jupyter. Only changing the type of the variable here, I change the browser I use. If I go to this method and I can change like this, here I'm going to use Firefox, okay? And also, I have more examples here. I can use several browsers, okay? Not only one browser, but two different browsers. In this example, I'm using two browsers, Chrome and Firefox in the same test, okay? I can declare whatever browser I want. Also, Selenium Jupyter provides integration with Appium, we will see an example later, and Selenite. Selenite provides a friendly API to use Selenium Jupyter in Java. If you are a user, you simply need to declare a Selenite driver type here, and you are going to use the last version of Selenite in your unified test. So, this is about local tests, sorry, local browsers, okay? Using local browser. I am running a test against my own local browser, iPhone, Chrome, whatever. The second big feature, let's say, about Selenium Jupyter is using remote browser, not only local, but remote. And for that, Selenium Jupyter provides two types of annotations, which are called driver URL and driver capabilities. We have, I have two examples here. One using Soslab. Maybe you hear about Soslab. Soslab is a cloud solution for providing web browsers and mobile devices for Selenium tests. We can say that as browser as a service, or mobile devices as a service, and it's very convenient, but you need to pay for that, okay? And also, we have an example about APM, which I'm going to run as an example. I come back to the code, and here in the remote package, I have these two tests. We can take a look. I'm going to use this one, the APM test. As I said, there are two annotations provided by Selenium Jupyter, driver URL, and driver capabilities. These user annotations are used at field level, in this example, can be used also at parameter level, okay? Basically, what I'm going to use, I'm going to say here is, well, I'm going to use an APM driver, because I'm declaring here, and to connect to the APM server, I'm going to use this URL and these capabilities, okay? I'm going to ask for a Chrome browser inside a mobile device, in this case, it's a Galaxy Nexus API 13. Well, I have prepared this environment, okay? You and your computer probably don't have this, but in order to run this, we only need the Android Studio. I'm going to run this. Basically, we need the Android Virtual Device utility here. It's open, so you can download it if you want, and I'm going to, well, to start this device, and also I need the APM server, which is a node application. You can also install it if you want. And you can see here that the APM server is listening to that port, which is precisely the port I'm using to connect, okay? So if I run this test I'm going to put like this. The test is again the same, okay? It's the test which opened the Selenium Jupyter documentation and verified the title. It's not there. And here you can see automatically in the mobile device that the test is running, okay? Not with the allocate, basically the same, but using this kind of remote driver capabilities. Okay. Let's load this. And now let's move on to the third part, third important part of the talk, which is about Docker. In my opinion, it's the most relevant part of Selenium Jupyter. As I said, Docker is a well-known technology to run portable containers. Basically, Docker has two important parts, the Docker engine, which is something we have to install in our host to run and create containers, and also the Docker Hub, which is like a cloud capability to push and pull Docker images. So Selenium Jupyter provides Selenium's integration with Docker using again an annotation. Since the annotation and the big blocks of the unit five, Selenium Jupyter also use. Because an annotation, in this case, I provide the annotation, Docker browser, to specify different types of browser and mobile devices to be used in Selenium Jupyter test. So the question is, what kind of browser we can use? We can use Chrome, Firefox or Opera, many different versions of this browser, even beta and unstable versions. And this version is maintained by the people of IOCube and the people by Elastest. These two projects are constantly maintaining these Docker images in Docker Hub. And Selenium Jupyter uses this work because this opensource and we basically pull these images to be executed in our machine and support our test. Also very interesting, we can use H and Internet Explorer inside the token container. Well, I can show you this running. The bad part of this is, well, H and Internet Explorer are supposed to be executed in Windows and because of the license, we cannot upload the Docker image and we have to build the image in the local machine. I did my machine and this is working, but in order to make this to work, we need to build these images locally. We need a license key. And finally, we have Android devices. These images are also in the Docker Hub. We can use these images provided by the Docker Android project. And all of these images can be used to support Docker browser within Selenium Jupyter. So let's get back to the code, which is the funny part. And here we have an example about how to use a test using, in this case, Firefox in Docker using the beta version. Here are the different important parts. First, Docker Roses, we need to specify which time of browser we want. And the supported types are Chrome, Firefox Opera, and Explorer and Android. Basically, what I told you in this slide, here we have the Java Enum to select one or another browser or device, in the case of Android. And then, optionally, the version. If we don't specify the version, by default, it's the latest. This is very interesting because by default, what Selenium Jupyter does is to connect to Docker Hub in the moment we execute the test and check the latest version. So this test is going to be somehow an evergreen test because we are going to use always the latest version. We can also use beta. We can use also an stable with this wheel cut. And we can use also this label, latest minus a number. Latest minus one means the previous version to the stable. For example, 85 is the Chrome stable. If we do latest minus one, we use Chrome 84. And this change dynamically, depending on the latest version of the Chrome, this text works in a sense or other. So let's get back to the code, which, as I said, is a funny part, in my opinion. And here in the package, Docker, we have different examples. For example, this one. This one has to test one using Chrome and another using Firefox beta, in this case. Well, if I want this, like this, I click the shortcut to run this test. Well, in this case, we are not going to see anything because everything happens in Docker. We can see the logs, which is not the most funny in the world. But we can see that we are using, in this case, Firefox beta. We are connecting to the Docker browser. And then when the test finish here, and this is the second test. In this case, we are using Chrome 85, which is the latest. For example, here, we can specify a given version. We can play with this. We can say, sorry. At the version, I don't know, it's 84, for example. I'm not going to run this. In this case, what is going to happen is that the test is going to go to, you see, 84. We have changed a version, simply changing a parameter in the test. If we don't say nothing, it's the latest by default, we can say here, for example, that. Well, this is the basic part of the new Jupyter using Docker, but there is much more, because using Docker browsers allows to, well, to use our rich variety of features. In fact, something very interesting is, we're going to try to see everything in this slide. First, the remote access with BNC. In this case, I run, we haven't seen anything. We see the trace. But very interesting, we can actually see what is happening inside the container. For that, we have BNC. BNC is desktop remote technology. And simply enabling BNC like this, by the way, this is the second way JUnit 5 provides the capability to define which extension I'm going to use. It's basically the same like this. The annotation extends with Selenium Jupyter. But in this case, I have access to the object. It's the same. I'm telling here, okay, I'm going to use the extension Selenium Jupyter. And in addition, I have the object. And in the object, I have the API provided by Selenium Jupyter. And in the configuration, I can make a lot of configuration. I recommend you to take a look to the Selenium Jupyter documentation because there is a bunch of capabilities. In this case, I'm saying, okay, I'm going to use BNC because by default, it's not enabled. Well, again, I'm going to use Chrome. In fact, we're going to make this or funny. We're going to use H, okay? Because Chrome, well, it's a well-known browser, but we're going to change this using H, okay? If you don't have this image in your computer, continue with Chrome. Chrome is going to be loaded automatically. But I have the H image prepared. And here we have the usual test I'm using in this presentation. And I'm going to wait a bit longer to play with the browser. Let's see. I run this test again. In the console, it's going to appear a URL, okay? That URL is going to be used to connect to BNC through a web application, okay? So because of H, it takes a bit longer than Chrome because here it's starting a whole Windows system inside a local container, but with a memory snapshot to be able to do it shortly. Here we have a URL. I am going to move this slide here. Yes. This is Chrome. This is the Chrome I'm using, okay? And this is a real Chrome, okay? I can navigate here. I can use... It has connectivity. It's working. Well, it has been closed because the test has finished, okay? Here, as you can see, the test has finished. And, well, I put the wait to 25 seconds. And after that, the test finished, stopped, everything. And for that reason, as you can see, the BNC connection has terminated. But the funny thing is we can interact with the browser, simply using this, okay? And, of course, we can change the browser, simply changing this, and read from it. But we are going to move forward to another very relevant feature. In addition to BNC, we can record what is happening in the browser. And here we have an example, okay? In this case, I'm using Chrome latest minus one, which is going to be 84, because now today the stable version is 84. In the future, this would be a different version, but today it's going to be 84. And what I'm telling here is, okay, enable the recording, okay? By default, the output folder is the same as the project. We can say that. But I'm going to show you here in my machine. This is the, no, it's okay. It's an individual example here. I have the source code of this repository. I'm going to run this example, okay? In this case, I have an active wait of five seconds in order to, well, to make a video of some seconds, at least, because we are doing the same test again. We're checking the same Jupyter documentation. And the test passed. But the interesting is that here has appeared an MP4 file. And this file, as you can see, is the recording of my, of my test, okay? Simply changing a line, I have the recording of my test. And this is very convenient to, to debug test. If you are Selenium, whether testers, probably many of you are these kind of people, you know that the most, one of the most, well, important things is that, well, we have a testing, a test which fails. Now we need to find which is the underlying fault. But what happened? Why is this happening? Well, a recording might help somehow. Not always, but a recording can be an offer step in that direction, okay? To diagnose what has happened with my, with my sister on the test. Then, okay, 10 minutes. Yeah. I'm going to go fast. I have to say that this workshop was scheduled at the beginning to 90 minutes. And I can't be speaking here a lot, but, well, I'm going to go fast. We have Android. I'm not going to use, to run this, but we can use Android also. And this, I think, I'm going to explain at least a bit because I think it's interesting. The template test is another feature, okay? It's a different feature provided by the Selenium Jupyter. I'm going to show you an example, okay? What is that in plate? What? Here, I have different examples. Basically, what I'm telling here is that this is not a test. This is a test in plate, okay? It's not a regular test. It's a test in which, well, the data is going to be provided with someone. And in this case, by default, the template is what I call the browser scenario, okay? It's a file which define which browser I'm going to use. It's defining in JSON, okay? It can be defining also in code, in Java code, but by default, it can be defining in JSON. And here, you see we have a Chrome Indocker version-late test, a Chrome Indocker-based version-late test, and one beta-less table. Okay, I'm going to reduce this in order to make this quicker, but I promise this is what this works. If I run this test, what is going to happen is the same test is going to be executed twice, in this case, one from Chrome Indocker, latest version, and one from Chrome Indocker, latest minus one. In fact, I'm not going to run here. I'm going to go further, and the last part of my presentation, I think, is going to be this one, the integration with Jenkins, which is something very relevant in my opinion. Well, Jenkins provides senders integration through this plugin, the Jenkins attachment plugin, meaning that the files generated by Jupyter can be read from the user interface in an easy way. I'm going to try to do it quickly. I have here a local instance of Jenkins, okay? I'm going to execute, and here I have prepared a Jenkins with a couple of jobs. It's searching. This is my local instance of Jenkins, and as I said, I have a couple of jobs prepared here. For some reason, it's taking long, but, well, here I have a couple of jobs, and I was speaking about the templates, okay? Basically, this job, what this job does is to, I can show you a bit, is to run a single test of Selenium Jupyter examples here. In this case, I'm doing something a bit, well, a bit more, this is self-scripting. I am grating the JSON file here in the same text configuration, which means I can change this simply in configuration. Then I'm running this test, okay? I run this then, and I'm going to do this configuration to store the recording and the screenshot. That's something I didn't mention, but another diagnostic technique provided by Selenium Jupyter is the capability to make screenshots at the end of the test. I know I didn't speak a bit fast, but I want to show you this in action. If I run this, this is going to execute the same test three times because the scenario defines three different types of browsers in the containers. The interesting part here, I'm going to show you the previous execution, is that when the execution finish, here is the test, okay? All the generated files are available from the user interface. This is the recording for the first test. This is the screenshot at the end of the test, and the same from the rest. This is Chrome, and this is Opera, for example, okay? As you can see, this is Opera in another container. In my opinion, this is very interesting because you can debug the test by inspecting what is happening in the recording or in the screenshot. To conclude, Selenium Jupyter is a Java tool that can be used in Java, but also can be used by a different programming language. For that, Selenium Jupyter provides two utilities, let's say. One is a command line interface tool, okay? And the second is a server, okay? We are going to see both, I think. The first one, as a command line interface tool, can be executed in two different manners, okay? From the source code, which is here. And also, for each release I made of Selenium Jupyter, I also made a release of what we call a FATJAR, that is a JAR file containing all the dependencies. So, if you download the FATJAR from GitHub, you can use the command line interface utility, for example, like this. I'm going to copy a command here. No, I copy 2x, sorry, like this, okay? I'm telling you here, okay, I'm going to use Selenium Jupyter, the FATJAR, in this case, to see a Chrome, in this case, version beta, okay? What is going to happen here? This is used for manual tests, because I don't have a test here, but what I have is basically the BNC connection to that container, okay? Here I have the URL. If I click this, I see here, that browser, okay? I have this browser, and as you can see, it's a working browser, okay? Here, I think, yeah. I have here the version, which is the 85, which is the beta, okay? And if I do this, I have five minutes, maybe? Okay, I'm going to conclude then. I'm going to conclude, yeah. As a server is like this, this as a server, and what is happening is, this is a Selenium Grid server, okay? You can use another test. I'm going to do this very, very, very fast. This test, use the Selenium server. You can run like this. Basically, it's a test. This is a JavaScript test, okay? But using the token container provider by Selenium Jupyter, okay? Okay, this, and you can see this is working, but this is the trace, and that's it, okay? It is that Selenium Jupyter can be used also for other users different to Java programmers. So, to conclude, well, Selenium Jupyter has a branch of capability, but it has many, many more. As I said, this question was supposed to be longer. I had to speak a bit, well, quick, but if you are interested in this, I recommend you to take a look to the documentation. And this project is a living project, I expect. I want to maintain this in years, and I have many different new features in the roadmap. For example, improve the test template support. For example, specify options. Using Kubernetes to improve performance test, which is something I didn't mention in the store, but, well, it's something interesting. And also improve the diagnostic capability by gathering mechanism of the project console, which is something very, very interesting, which is still to be doing a lot of it. And that's all. Sorry for speaking so quick. I think we have some time for questions. I don't know if we are running out of time, maybe. I feel very bad to have to pause you, Bernier. It was so interesting and exciting, all these features. And would have loved for it to be an actual workshop, not just 90 minutes, but people can participate and learn how to use Selenium Jupyter. It can make life of automation so much easier. Test will become so much stable. So thank you very much for sharing these experiences and what you've been developing. And thanks to our sponsor again, Browser Stack for sponsoring this session. Thank you, everyone. And talk to Boney in the VIP launch. Take care. Bye-bye. Thank you. Bye-bye.