 So my name is Sigur Kroll and I will talk today about Selenium and JavaScript, how to enhance your tests via JavaScript. So I'm a bit worried and it's pretty unusual for me to speak in English, even so far from home. I'm from Belarus, by the way, who knows where it is. Okay, not so many people, and of course it is to the north of Ukraine and to the west of Russia. So somewhere there. And I'm working for Wargaming.net, who knows what we are doing and what games we are developing. Okay, oh, even more. So we are doing games, so we are doing games which are related to war. Actually, the most popular game, our game is World of Tanks. It's pretty popular, but mostly in Russia. But, friendly speaking, I'm not game developer. I'm doing all the things which is related to the web in game development. So all the things which is working with the web, but is related to game. It is what I'm responsible for. I'm doing test automation for lots of years already, thousands of projects in different roles. Mainly, I can name myself as engineer, but try a few different roles like trainer, cloud manager, blah, blah, blah. Working with Selenium for more than five years, I believe from something like 0.9, I believe it was the first version which I've met Selenium. I've tried to share my thoughts on the blog. Unfortunately, English version is not so frequently updated, but anyway, if you will find something useful, I will be glad. So, what I'm going to talk today about, there will be two parts. One is theory and some reasoning, some general judgments. And I will present you some practical cases how to use this idea on your practice. So, firstly, I would like to show you this diagram about theoretical part. So, it is the same as test pyramid, but a bit different way. So, on the horizontal line, we have technical level. So, the lower level is to the left, the higher level is to the right. And amount of support and amount of testing that you should have, it is red line and green line. So, the lower tests we are writing, the lower technical details we are dipping into, the less support we have. And vice versa. So, Naresh few talks ago already represented this idea in different way, but I will not duplicate him. What I can see is that the majority of the projects are focused somewhere here. So, we're getting lots of support. That's why we can't throw out much of tests, et cetera. So, I hope after my presentation, we will be able to do at least some shift, at least some. So, I'm not trying to convert everything, but I will try to show you some practical steps how you can dig into technical details from the level where we are right now. Firstly, first statement that we should understand that UI tests are unstable. So, I don't see any company, any projects where UI tests were constantly green, like unit tests. Unit tests are more or less green, but if UI tests are green in 95% of times, it is great success, I would say. So, one of the reasons why it happens is more than user interfaces. So, we are not in simple web anymore. We have lots of these technologies, GWT, JQuery, Centra, XGS. All this stuff is within our browsers, and we are trying to handle it using our JavaScript, our Selenium test. Two features of these user interfaces. Firstly, they are complex, and secondly, they are asynchronous. So, this is the main cause of the problems. But it is not so good, so bad, just because modern user interfaces are based on prepared and already made components. So, we are not writing lots of, we are not writing new JQuery or new GWT. So, we are reusing it for our needs, we are providing them. So, the main goal of usage, if the problem was solved once, so our development world tried to not to solve this problem. Another one, that's why we have such many user interface frameworks. And already made components, they could be less tested by ourselves. So, we got some component which was developed by other guys, from open source, from some commercial framework anyway, but we got it already delivered, we got it already tested. That's why there is no need to test it by ourselves again. This guy is from Russian fairytale, who is so lazy, he drives this stuff. So, custom, even if you wrote custom components, they could be tested separately. They could be unit tested. I provided one example of this framework, but there are lots of them, or some of them were mentioned already. So, even if you wrote your own custom code in order to build your user interface, it could be tested separately. So, using lots of frameworks. But it is not what I'm talking about. The next statement which I want to mention is the majority of the modern user interfaces has internal API. So, it is apidquery.com. It provides lots of methods. It's hard to even understand all this stuff. So, you can do everything. And this API, what is their benefits? They are built to interact with user interface components. When someone developed a library, it is not just library in the vacuum. It is a library which should be somehow programmed. So, they provide the API in order to interact with these components. And what is more better, this API in most cases is synchronous, or there are methods to synchronize. So, we already, in addition to the already made components, we got API with these components. So, there were lots of different statements. In order to summarize what I said, we have majority of our interfaces are based on some bricks. These bricks can be left untested or tested separately. And components has their own API. That API is more reliable than WebDriver API. WebDriver API is excellent, but it is not designed to interact with that particular components. So, result, let's use JavaScript API instead of WebDriver. That's the main theoretical part of my speech. So, life example. It is not just general speech. There are proven cases by myself where it works. First example I want to say about Oracle Siebel technology. Does anyone here know about Siebel? Okay. It is a commercial tool with closed source. But this idea worked there. It's not about just some funny, agile companies. It is about pure commercial development for a great company. So, using the face of Siebel has different characteristics. It has lots of frames, which is even more worse. It has activities. So, it is what should be automated in this case. And initial solution was pretty direct. Like you should see, find element, click something, see in the browser what's going on. It was done via WebDriver API, which we are all familiar with. What were the difficulties? Interface was very asynchronous. And methods worked unstably. First run, it works. Second run, it doesn't work. I should wait for something, but everything is so close within ActiveX components so that I can't understand how to synchronize all this stuff. So, there were lots of frames up to five nested frames in order to reach control. So, you should switch to frame, switch to frame, switch to frame, switch to frame five times, and then click button. So, that was totally nightmare. And impossibility to work is with ActiveX at all. So, it stopped all beginning with Selenium. But the solution was pretty simple. If you will Google just what I can do with the user interface of Siebel, I found official Oracle documentation which describes how to write custom code on browser side using Siebel technology. So, Siebel logic could be implemented in both sides on server side and on client side in the browser. So, it is API which is provided by Oracle which enables developer to implement custom logic on client side. So, why not? There is an API. It should provide some abilities which I need for my tests. Examples. So, I got standard remote driver. It implements JavaScript executor. And instead of clicking buttons, I started to invoke methods, internal methods from Siebel, from the browser. So, using JavaScript executor, we can execute any JavaScript. So, it looks ugly, of course, because I need to concatenate lots of strings and there is a JavaScript within Java code. But anyway, it worked. So, it worked in this simple case or if I need to provide some parameters, it was a bit huge, but all these JavaScript pieces were encapsulated within the course of the framework. And outside, it was like regular script using business logic. I need to do this. I need to do that. But internally, it didn't click buttons. It invoked Siebel API methods. The result was quick. I didn't need to switch to frames. It was reliable because if this API is not reliable, this means that Siebel provides API which works unstable and even if developers wanted to implement something and the API unstable, the result will be unstable as well. And it was synchronous. So, it was really good results, but of course not without problems. As you might feel. So, firstly, methods were synchronous and if some method invocation causes outlets, and this can be done simultaneously. So, I can't finish JavaScript execution until outlet is not closed and vice versa. I can't close outlet because JavaScript execution is not finished. So, how it was solved? It was solved via this feature, Windows set timeout, who is familiar with JavaScript who knows what it means. Please. Yeah. So, we are providing some JavaScript and saying, hey browser, please execute this piece of JavaScript after setting amount of time, but without under some background. So, what we said that hey JavaScript, execute please, but after zero milliseconds. So, it is like multi-threading in JavaScript. It looks not so obvious, but it works. We lost 100% in user simulation because that driver concept is designed in order to simulate and use a behavior. When we are calling JavaScript, we are losing it. But at the same time, the whole user interface, it wasn't written by our developers. So, it is generated automatically by Siebel. So, it was tested by Siebel. It was tested by millions of users of this technology and why I need to do it one more time. So, that's why it is disadvantage, I understand, but it is not so critical comparing to the situation when we can't do automation at all. So, it was first case about the technology that you don't know, but it works. And let's talk about jQuery. Here, I have actually two questions for you as an audience. Who knows on which technology your user interface is built? So, I see about 50% of the audience. So, this is... If you don't know, you should know. So, that's the idea of this approach. So, it is the moment where you should even start. Understand what is under this black box that you are testing via Selenium. So, I selected jQuery as an example which will be more interested for everybody because official statistics show that jQuery is the fabric which presents on 60% of current web almost more than a half. So, whose site is built using jQuery? So, from 50% who knows, 60% raised the hand. So, let's talk about jQuery. How we can use jQuery and jQuery API in order to enhance our tests. Even if you don't have jQuery API, you can put it into your site. So, it could be injected on runtime. So, the first thing that is really good and there are lots of examples of this on the Internet, it is about synchronization. If you want to understand where the user interface is already rendered or not, so you can check this property. This example was in Java, this is C sharp, but it doesn't matter. So, what we're trying to check, we're trying to check internal jQuery property active to be zero. It means how many active operations jQuery uses and if your developers are not walking around in these jQuery things. So, this indicator will show that, okay, user interface is rendered and the next operations can be done. Next one. Oops. Looks like space. Sorry for technical issues. Just a second. I will reopen it. Oops, oops, oops, oops, where we are. Oh, finally. So, in order to interact with JavaScript or with jQuery API, you need to use internal jQuery objects. So, jQuery objects, it's not regular web elements, it's not regular DOM nodes. So, we need to know how to convert from, how to switch from web driver to jQuery and vice versa. So, it is a piece of code on Python which shows how to get jQuery object and convert it to web element. So, we are executing script, trying to find element by ID and this dollar, commerce, slash, hash. So, up to the dot get zero, it is standard way in jQuery to find object and then we are converting it to regular DOM node and returning it to web driver. So, and then it's regular web driver object which way we can send keys. This script is really replacement find by ID. So, it is the same. But using jQuery. And vice versa. If we found element, we can put it, we can provide it to JavaScript using parameters of JavaScript execution and using dollar brackets, we can get JavaScript we can get jQuery object from web driver object. So, it is the same example which sets the value for input which was found by web driver but input itself was done using jQuery. So, is it clear? Just it's basis where next example I built. Going next. The question yesterday was about how I can find, contains, about contains. Yeah, so contains is a method from jQuery and visible as well if we want to find element by ID which is visible. So, it is an example. So, and trying to do send keys, it will not work. Actually, we will go to an exception. It will not work. But we can convert the same to jQuery. So, we can find element by any set of classes from jQuery which are available and then use this as regular JavaScript, as a regular web driver object. So, that allows to do all, to use all the power of jQuery in order to locate elements. Another example is if I want to get parent element of, I can do it using expath, but if not, I can use, actually I can use any method of jQuery and one of useful methods is to parent. So, I can, I have my web element, then I convert it to jQuery element and get it parent and then return back corresponding web element which feeds to this jQuery element. So, it is an example. How to handle it? Even if you have something more complex, like calendar. So, a regular way how to pick date in calendar is to open calendar, select year, select month, select blah blah blah all this stuff. Hey guys, this calendar is retrieved from standard jQuery library. It was tested. We know that it works. So, why don't we emulate and use it in order to do all these month selections, all this stuff. So, it is an example how we found a calendar by ID and then set date using jQuery API. Without all these synchronization things, without all this nightmare, without all these algorithms. Thanks to Alexey Baransov, who is one Selenium Commitus, who provided this example. But it is not something magical. You can go directly to your documentation of your library and see how to set this date. This example is really not from, is not something extraordinary. It is standard method from jQuery. Even Google open jQuery and see how it works. So, it is not something which I really invented. Even if you have custom controls. So, it is example from my project where we need to select a country for user. So, we have custom controls. We are gaming combo box. That's funny thing, of course, but in order to select value in this combo box I need to click, drop down, I need to scroll to certain piece of code, to certain place, because there are lots of countries. And click, and then wait while this value is applied. All this stuff should be done and I believe it will work unstably. And I will debug few weeks in order to make it work. But what we have done, we opened sources. You can do the same yourself. So, you can see that even the developers of custom components, our developers, provided the description how to set this value programmatically. So, if you want to set this value for this control, call this code. That's it. And it's really an example how to select the country in this control. So, find and call the value which was provided by documentation. So, it is even if you have custom. Of course, you should write some additional scripts in order to, some additional tests, in order to test your custom component using any unit test tool. But for your end user test, it doesn't matter because you tested already control this, this widget or whatever you have. And there is no need to retest it every time when you are selecting value in combo box. So, summarizing. The general schema looks like the following. We have tests, we have visible user interface and browser who works with this user interface via HTTP protocol. But our visibly user interface is built on some libraries. We're not writing JavaScript code from scratch anymore. If you do, there are maybe questions to your development. So, and library in addition to some core and components has API. And using JavaScript executor, we are calling these API methods in order to interact with user interface. So, that's general schema how it works. Another way to apply this approach is to work around existing web driver issues. Of course, web driver has defects. So, for example, click doesn't work. And as yesterday already mentioned, we can do the same via JavaScript. So, this is pretty simple example. We are calling not really your components API. We are calling methods from regular DOM structure. So, but you should use it wisely. So, it is really important. Just I need to mark it really red. So, it is not the way how you should do constantly these clicks. You should not. Because in this case, we are evolutionary, we are coming back to Selenium AC, which was built on really on JavaScript. We are writing new Selenium AC using our framework. So, it is just way to work around. You need to do quick release. You know that click works. You don't have time in order to debug the issue, in order to fix the issue. But you need to have tests green. So, only temporary. And it's important to understand why standard approach doesn't work. Maybe even you have issue. It can be the case. But it is really reproducible. You know what it can be. You should deep into technical details. So, and after that, post a bug to, with an example, of course, to Selenium community to, in order to be, to have it fixed. So, okay. Summarizing what was explained, what I wanted to say. Digging into technical details allows us to write more reliable tests. So, don't look at your system like in black box. Try to understand what is within it. And you're learning, if you don't know JavaScript and you don't know what your library is used in order to create your user interface, it is natural next step in order to grow as engineer to learn what, how it built. Because we are dealing with this user interface. We should know how we, how it's built. But we should understand what we are missing and find balance. It's all about trade-off. So, we are getting something, but we are losing 100% end user simulation, all these things. Thank you. Questions? Any questions? It was so obvious. The question is, is it good or not? Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. You should understand your internals, what is built. What? So, the question was about the following. I have two drop-downs and one third drop-down is based on first two and we don't know what way to use in order to understand that third drop-down is populated. So, the answer is not, there is no common answer to this. You should understand how it's built. So, if there is no way at all to, so you should use explicit weight in order to see drop-down. But in general, it depends on your implementation, really. So, if it is pure jQuery, I give an example how to use it. But if it is not jQuery or your development work around in somehow this active, then it will not work, of course, and you need to do something else. So, the trick is in understanding what's going on with your user interface. Yeah. So, you have to put even some testing code into your application in order to do repeatable operations. So, not even to call it externally, but to have it within your system and to, am I right? Yeah, yeah, yeah. So, there is a method specially written for such kind of approach. Anything else, guys? So, if not, thank you all.