 Welcome, everyone, to the Solving Wordal with Python and Selenium and running that in Gradle GitHub Actions by Michael Mintz. We are glad Michael can join us today. All right. Thanks, Nudi. Hello, everybody, and welcome to Selenium Conference India 2022. In today's presentation, I'll be using Python and Selenium in order to solve Wordal and there are a few different versions of the Wordal website. So if anyone is not familiar with Wordal, it pretty much looks like this. You get to guess letters and figure out what the correct word is. And if you get a yellow letter, it means that the letter is not in the correct place. And if you get a green letter, it means that it is in the correct place. So I'm going to start a screen share so that you can start seeing everything that I see. This is what Wordal looks like. You have yellow letters and you have green letters and you have to guess the correct word. And it gives you hints by telling you what letters are in the correct place and which letters are in the incorrect place. So we can use automation to solve Wordal. So if we do PyTest, Wordaltest.py, it's going to run a Python program that guesses Wordal for you. So it's going to load up the page with Selenium and then it's going to start guessing words and it's going to take the hints that it has there and try to figure out the correct word. So here it's now on the fourth try and there you have it. It solved it in five tries bluff. So if you're wondering what that script looks like, this is the Wordaltest. It's some simple Python but essentially it's going to open up the New York Times website which has the Wordal game and then it's going to initialize the word list which basically searches through a preexisting list of words so that you can see, so that it can generate a full list from that and use that to make guesses. Now the full Wordal list does not include all possible five-letter words. They've basically pruned the list in order to make it so that maybe bad five-letter words don't show up as possible solutions. That way it's still, you know, friendly, kid-friendly, etc. So if anyone is wondering how that script works, there is a Python Web Automation framework that I created called Selenium Base that essentially allows you to work with Shadow DOM more easily, click elements. It automatically waits for page elements to fully load before interacting with them so that you don't need additional sleeps or waits in the code. This Selenium Base is available on GitHub. It's open source so you can see all the code if you're interested. Particular examples that we run are found in the Selenium Base examples folder and there's hundreds of different examples and in particular here, the ones that we are going for are the Wordal test and basically it goes through, it uses the algorithm to determine whether or not the yellow letter is there or a green letter so that it can guess the correct word based on the hints that it had. I'll run it one more time just so that you can see it in action. The Selenium Base tests run with PyTest so I can do PyTest, WordalTest.py and it'll automatically spin up the web browser and start playing Wordal. You can see here, it's guessing letters and here we go. Once again, it guessed it in five tries but every time it runs, it runs a little bit differently because it's using a randomized algorithm. Now, about a month ago, the website had a full redesign and they got rid of all their shadow DOM elements which basically is a page within the page. In order to show you how it looked on the original site, we can use the web archive in order to see the original Wordal page before they changed it. If we do PyTest, Wordal, Archive, Test.py, it's going to open up the web archive which is basically a copy of all past websites so that you can see how the Wordal game did in previous renditions. It's going to be a different word than you saw before because it's using an existing version of the website that was there previously. It guessed Ample in three tries there and if you're wondering exactly how that website looks underneath, we're going to open it with the web archive so that you can see the shadow DOM that's there. I'm going to right click and inspect the element which basically allows you to see the HTML source for the page. Inside, if you can see clearly here, I'm going to expand it so that you can see a little more clearly. Inside this website, there are these shadow root elements and shadow root is basically the shadow document object model which basically has a website inside a website and interacting with these shadow elements. In order to do that, you need Selenium 4 and you need the latest version of Chrome or Chromium browser and from there, you're able to interact with the shadow DOM elements in order to click the buttons and pretty much interact with the page. Now, the shadow roots definitely complicate the interaction with a web page because you have to specifically jump into the shadow root before interacting with it. If you wanted to say click a specific button, I'm just going to exit out of there, you need to basically interact using the shadow root because you'll switch in and then you'll click inside. If we were to go into the script that interacts with the shadow DOM, we have here the test wordl archive test. You'll see that it uses a special syntax such as here to interact with the shadow DOM elements more easily than you would if you were going to directly use a Selenium command to do that. So it uses the colon colon shadow selector. It's basically a unique selector to Selenium base, but essentially it'll go to this selector, it will jump into the shadow root that is there and then it will look inside for another element and then it will let you jump inside the shadow root again so that you can click the game icon. For instance here, this lets you close the initial screen that pops up whenever you go to wordl for the first time. So this is interacting with shadow root elements using wordl. So now that we have that, let's jump back into the example that we have here. So essentially if you weren't using Selenium base to get to the shadow root, you'd need to use a command such as this to click it and it gets much longer because you have to individually pierce the shadow root elements. So first you could do something with python driver dot find element by css selector the game app and then you could do dot shadow root and dot shadow root will then take you inside the first level of shadow root and then from there you'd have to find another element inside of it and then keep going through the shadow root so that it becomes a significantly long line. However with Selenium base it simplifies the interaction with shadow root so that this giant line here can be done entirely with just a self.click line a self.click game app and then it pierces through the shadow root and lets you basically interact. I'm going to run that test again so that you can see it interacting with particular shadow roots from the wordl archive website. So it's loading in now and this is the version that has the shadow root and it's picking a random wordl from the past. These are some terrible words here that it's guessing. Let's see. Guess that in three tries. I'll run it again just so that you can see that it's going to pick a completely random version of wordl from the past and every time it runs it's going to guess different words in order to get to the final word and let's see try number four shell. Okay so here the word was shell and it took four different tries to guess that. So if you're wondering how to run any of these example scripts that you see here all that is accessible from the Selenium base website where you'll find examples like this and many others. So let's see the one that we just ran here with the shadow root that is the wordl archive test and I'll just walk through how the whole script works. So first it's going to generate a random wordl from the past using the existing format that is set up for it. So if you look inside this page here you'll see that it uses the web archive which basically allows you to see a past version of a website if say a website later changes you can go back to a very specific date. So here 2022 this one was April 17th and had a timestamp from that day and it used the wordl website so it basically went through and found the past wordl in order to get to that. So I generate a URL that looks like this from here so that I can get to the past wordl version and then I initialize the word list and then I basically pick a random word. So I do word equals random.choice self.wordlist in python this random.choice essentially lets me pick a random item from a list of words and the self.wordlist I already pre calculated at the beginning which basically has all possible five letter words that will be available when you're guessing wordl. So random.choice gave me a random word and when I started guessing I basically mapped out the various letters inside wordl so that I can click the buttons and after I go through a round of guesses I basically try to calculate what letters are yellow and what letters are green because that will tell me whether or not I've guessed a correct letter or a letter is not in the correct place and it goes through this algorithm at the top here where I modify the word list where essentially based on the hints that it gives me I prune out words that are no longer possible because the letter isn't there or it's not in the right place etc and therefore I keep shortening the list of guesses that I have until eventually I keep clicking through and there are no other guesses that I can do and I'll eventually reach the correct word hopefully in the six attempts that I have. So I'm going to run the wordl test on the latest version of the New York Times website and it's going to run a little faster because it doesn't have to deal with the shadow DOM because they changed the website. So here a guess snippet it saw that the l was not in the correct place so it's going to use those hints in order to try to guess the correct word and as you can see here it took those hints and we basically solved wordl and you can run it every time and every time it's going to run a little different because it's using a randomized word generator that basically will sift through all words that are still valid. All right so let's go back to the main thing so I just want to make sure I'm covering all the main things that I want to cover in the presentation. Why are we automating wordl? Well it's fun to use selenium to play games and solve puzzles that aren't necessarily around test automation because selenium isn't just for automating testing of websites it's used well for basically automating all sorts of tasks that pretty much anything that you want to automate on the web. Anything where there's a web page you can interact with the elements and essentially make anything possible. Now that we have wordl running we can now take the script and run it inside github actions so now that we have that let's take a look at one of the github actions that I have running that's actually solving wordl. So you'll see here in the MD men selenium based examples under github you have github actions and if you click on say the top one you'll see that the script has been running on ubuntu mac os windows etc so let's see if we click on one of them and we jump all the way to the wordl test you'll see that the word guest was bluff and it got it in five attempts so this is an example of using github actions in order to run wordl and if you're wondering how exactly to generate the script for this let's see that github actions file will look like this for instance for python python package dot yml and the dot yml file represents yaml format which is the format that you'll likely be using when creating automation to run in github actions so to create that file you could set it to run on a cron schedule which is what I did which basically means it'll run at the 30th minute of every hour and it will run on the main branch and you can specify all the various os's that you want to run on such as ubuntu 20.04 mac os windows etc and the python versions so right now I'm running that script on three seven three eight three nine and three ten uh you set up the matrix uh you'd install dependencies and the main one is a slunning base which is part of the requirements file and you run python setup dot py install from the git clone and you'd also install google chrome you can also install edge and run it there as well and once you've uh installed the drivers and you can do that with a command such as slunning base install chrome driver or slunning base install edge driver or gecko driver etc those will download the automatically the slunning base web drivers that you need in order to interact with the web browsers that you're spinning up so from that script uh there's multiple different examples here and the one particular it's the wordall test and I run that at the very end and in case it can't get it in the six guesses that it has well it's not a total guess because it's using hints so it's very educated guesses where it prunes out the words uh a command such as dash dash reruns equals five it's basically a py test option uh which will allow you to rerun a script if it fails and in case that wordall because there's a lot of randomization involved if it's like a really tough word to guess then I make sure that there's plenty of room to get that word so that when it actually runs in github actions you can see all right I want to know how it's running on the latest version of windows and it runs a script and let's see here it took six attempts to get bluff etc so this is github actions and it's really easy to just work from an existing um dot yaml file in order to set this up uh I'm going to go into the chat box and see if I can answer people's questions oh can you provide the github repo link absolutely so the github repo link for selenium base I'm just going to copy that and post that into the chat so that is the link to the main github page if you're wondering where all these github actions are running so that is just this link here I'm going to copy that into there so that's the github actions that's basically running all those wordall solver tests on continuous integration and github actions is one of many different continuous integration systems jankins is another popular one there's gitlab here we're using github actions because it's completely free for open source projects so if anyone wants to run their own workflows on a cron schedule they can easily do that for free and if people aren't sure how to create a new workflow you can go into actions new workflow and it'll even show you how to get started so that you can start creating uh your python packages etc that uh you might want in order to basically create a whole github actions workflow for that and you can use like anaconda there's a python application there's a published python package or just python package which is the simple one that I used and it helps you get set up but if you're looking to run something more advanced uh you can use the existing scripts that I've already created and if you're wondering just a little bit more about the github actions for the sunny base examples all that can be found in the uh let's see I've got an empty men's github folder sunny base examples and if you go into dot github slash workflows uh this is the general location that you'll find uh your github action scripts and that's where you'll find your python package dot yml file and you'll immediately get the script there where you can set the cron schedule and you can set how many parallel uh tests to run at the same time such as here you basically copy paste the script and then modify it you can easily make changes so that everything is already set up and ready to run it automatically takes care of installing web browsers for you for your tests as well as showing you how to structure uh a test run and if you're wondering you've probably been looking and seeing that we're using py test to run all the scripts and py test is essentially uh python at unit testing framework I know I'm going a little bit out of order jumping around like getting to the main examples then going back taking a step back and saying oh by the way py test is used to run all the scripts that you see here and it's probably python's most powerful unit testing framework it gives you a nice structure and gives you like output so that you can see what's going on and you can even uh generate a fancy report so let's say I run the script again and I want to add a few additional command line options such as dash dash dashboard and dash dash html equals report dot html if I run the word test now it's going to uh create a dashboard and a full test report of everything so that you can see exactly how uh everything looks uh as a test report and py test html reports uh is a common py test feature so I'm running it again but this time I use the advanced command line options so that I can generate the report dot html file so if I open that you'll see that it's generated uh basically a dashboard it was one test that ran and it passed and you get a nice little pie chart and it shows you that it ran the word test and it took a duration of 26.67 seconds and it also shows you useful things such as in your environment what your platform was which was mac os here uh the py test version that you had the different plugins that you had so this right here is py test html with the selenium-based dashboard included so you'll see the py test html version and other plugins such as ecstis which lets you run py test tests multi-threaded uh there are also other plugins that can be used such as rerun failures which will let you rerun failing tests uh I'm just going to make it a little bigger because you probably can't see it when it's small rerun failures which lets you rerun a failing test you can use py test ordering to set the order of tests etc and of course there's selenium-based which is the py test plugin that lets you uh do browser automation and everything like that so it ran one test and it gave you the output there and if you're wondering a little bit more a more simple example of selenium-based since we jumped right into some of the most complex tests that you'll have uh if we wanted to do a much more simpler test such as let's go to test swag labs I think there they are one so swag labs is the sas demo website it's one of the sponsors of selenium comp they have a nice e-commerce website where you can essentially uh login add an item to a cart and then check out so if you're wondering how selenium-based works there's lots of simple methods such as type so that you can type into a css selector it which is the default which makes it easier so that you don't have to specify whether or not it's x path or css it'll auto detect and then it will go through uh I'll show you what the website looks like just so that you can see how sas demo works so it's a pretty uh easy website for basically doing all sorts of things on an e-commerce website it gives you the login information at the bottom standard user and then the password for all users is secret sas you log in you can add an item to a cart uh once you've added the item to a cart should be able to click on the cart and you'll be able to check out then you can just type in some fake data and doesn't really check that the main idea is that it's a simple website that you can use for practice testing and you can see you've added an item to the shopping cart and you can click finish and then it says thank you for your order and uh you can use selenium base to automate that as well just to take it down from shadow dom and complex swirl solving it's more deterministic because the website is the same every time it's not like a new item in like a new list of items every day so if I run py test test swag labs and it'll just do a simple test just so that you can see selenium base handling all sorts of things so it's going to login it's going to add an item to a cart it's going to check out and verify one of the cool things that you can do with selenium base is slow the test down with demo mode so that you can see exactly what the test is doing as it runs so if I do a py test and then the test I want to run and do dash dash demo as a py test command line option it's basically going to highlight the various items that are on the page that's going to interact with so you can see that it's highlighting the fields that's going to interact with and whenever there's an assertion it's going to share at the bottom of the screen assert like css selector or here at the bottom the inventory item that it's checking so you can actually see not only where it's clicking where it's typing but you can see the assertions that are being made so that you can say oh if you add an item to a cart that the text says remove on the button instead of add to cart so it makes it really easy to see what tests are doing which is very convenient and you can see that demo mode it's just it slows everything down but it shows you what your test is doing so that you can see everything that's going on so here it's verifying that you know the various buttons are there like cancel and here it's going to slowly type in the fields that are there and you can see that's verifying all that that it verifies that the test all the things t-shirt appeared in the cart and it's showing all that that's there so demo mode is one of many available command line options that you can use alongside your selenium base tests in order to get more out of the test if you're wondering about additional options so let's just go over to the main github page you can see the py test options for selenium base you can easily change the browser so as you saw before chrome is the default browser if you don't specify it you can change the browser so that it runs with edge firefox even safari uh let's see you can multithread the tests by using dash and four and this is using some built-in py test multithreading so if you have a lot of tests that you need to run at the same time uh py test multithreading is the way to do that what you saw earlier was the dashboard with the html report that i showed about 15 10 minutes ago that basically can give you a full report of all your tests after it finishes running there are lots of ways to debug tests such as using the dash dash pdb option which means that if a test happens to fail it will pause and then give you a debugger so that you can do live debugging right then this will let you rerun failing tests if you want to do that there's a recorder option so that it can record tests and i don't know if i have time to show you that but the key thing here is if you want to use one of these selenium servers from our sponsors such as browser stacks saw slabs lambda tests etc you can run any of your py test tests uh on one of their selenium grids by specifying the grid server the key and the ip address and maybe the port that you'll need it could be 80 maybe sometimes it's 4444 and if there's authentication that is in the key now essentially let you run your tests on browser stack saw slabs lambda tests etc and utilize all of their advanced features uh there's also selenium based mobile mode which will kick off chromium's mobile device emulator so that if you have a test that has a mobile version of a website you can just do that and it will use default mobile device metrics so if I just do let's see py test my first test dash dash mobile that is going to go back to the saw stem of site but it's going to use the mobile version which as you can see it's uh slightly different from before and you'll be able to run a mobile test not just the regular web test just by adding the dash dash mobile as a command line option and of course there's a lot more options that you didn't get to see here uh but there is a full list on the selenium base page on github the dashboard looks like this so if there's a lot of tests you can see your failing tests your passing tests uh here's what it looks like with the uh you know some failing tests at the top and there's logs so that if there is a test failure you can see what went wrong and we didn't run any failing tests right now but I'm just going to quickly do py test test suite and then dash dash html equals report dot html and dash dash dash board and dash dash rs I'm just going to do a quick one more quick uh suite of four like two second tests so that you can see what the logs look like when a test fails you know take screenshots and all that and give you all the info so here we have a dashboard dot html so if we were to open that inside a new window you can see that here it ran four tests where two failed and two passed and inside the data folder you'll have things such as basic test info which shows you the tests that you ran the last page that it was on the browser it used the driver and the date that it ran with my time zone etc and then the stack trace and the most important thing it will have the screenshot right here that you can click on it and see what went wrong all right let me go back to the uh chat so we have q and a let's see we have a question from Vishnu uh in the word puzzle how is it identifying yellow color and proceeding further and how is it identifying green color okay so inside the website when you're running word all so i'm just going to quickly get that back so that we can see oh chat window is blocking the screen oh there we go okay so uh on the website itself we're going to quickly i'm going to show you how that looks so if we go to word all it's going to quickly jump directly to it if you if you guessed a word such as stuff i think the answer was bluff and we're going to do enter if we right click and inspect the element it'll actually tell you whether or not it was a green tile or a yellow tile because if you inspect it inside there it will be in the html so let's see data title data state equals correct there that is the main thing there so if you have a word in the correct place or a letter in the correct place it's going to show a data state property equals correct now if it is in the wrong place it'll say uh or it's not the letter is not there at all if i go here data state equals absent because there is no uh t in the word so if i were to uh do let's do blunt where letters aren't going to be in the correct place you'll see oh that's not a good one because uh let's do here we go there's a yellow one so here the u is in the incorrect place so you can do data state equals present and inside the html based on that you can say okay the word there the letter u is not in the correct place but it is in the word so the css selector for that would be data state present there all right let's see uh back to q and a uh any more questions technical all right well we're going to do a quick one more quick thing uh for the recorder so that you can see how the recorder works uh let's see i'm just trying to there we go let's move that out of the way if we do s space recorder it's going to start the recorder desktop app and let's say we want to do a quick recording so let's do sauce demo.com and we're going to click record it's going to go here and if i copy standard user in here and i copy secret sauce in here and i do a login and i'm going to add three items to the cart and then once that's set i'm going to click on the cart item and i can verify that things are there so i'm going to uh basically i could verify that that says it's 1599 that's 49 and that's that and then i'm going to click checkout i'm going to type in hello selenium and then one two three four five continue and then i'm going to click finish and i want to verify that it says thank you for your order so i'm going to switch into assert element mode and then once i'm done recording the actions i can type c and it's going to generate the recorded uh script so this is just one quick way where you can use the selenium based recorder to generate a full script so you saw here that i went to this website uh it saw that we clicked the item and then it generated the script so that will allow you to quickly uh play back the script that you just saw so that you can quickly create tests and if you need to generate a new test on the fly you can use the recorder to do that so here you have it playing back a recording so selenium based recorder is sort of like selenium ide except uh it's python based uh let's see if i can answer anyone's question so that pretty much uh covers everything uh hi niddi how are you doing thanks for the session maiku anyone have any questions i didn't get to cover uh everything but as you saw that you can use selenium based and python and selenium to solve wordl and interact with the website easily interact with shadow dom and you can generate scripts easily with the recorder and use additional command line options so that you can see reports and etc or demo mode so that you can see exactly what your test is doing and you can easily connect to a grid server for say browser stack sauce labs land to test etc our sponsors here so that you can run your selenium based python tests on one of their grids thanks maiku for sharing your experience with us today