<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Selenium – general</title><link>https://trunk--polite-jelly-cc0866.netlify.app/categories/general/</link><description>Recent content in general on Selenium</description><generator>Hugo -- gohugo.io</generator><lastBuildDate>Tue, 09 Jan 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://trunk--polite-jelly-cc0866.netlify.app/categories/general/index.xml" rel="self" type="application/rss+xml"/><item><title>Blog: Selenium Vs … blog posts</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2024/selenium-vs-blog-posts/</link><pubDate>Tue, 09 Jan 2024 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2024/selenium-vs-blog-posts/</guid><description>
&lt;p>The easiest way to clickbait a blog post about automated testing is to compare Selenium against another tool in the space with a catchy title especially when it talks down about the incumbent.&lt;/p>
&lt;p>Unfortunately, this can lead to muddying the waters of which features are available in any of the products out there especially when we compare apples to apples.&lt;/p>
&lt;p>Selenium has always been a great tool for browser automation. Fortunately for the project, it has become the tool of choice for testing web applications for nearly 2 decades. The area this project has focused on is building out the hard parts of browser automation that are increasingly difficult. Stable APIs and scalability of the infrastructure to run Selenium has always been the priority of the project. It hasn’t focused on how people test with it because there are very good test frameworks out there and having to do it for 5 different languages is a non-trivial amount of engineering effort.&lt;/p>
&lt;p>However, some particular misconceptions regularly reappear across these blog posts.&lt;/p>
&lt;h2 id="its-too-hard-to-set-up-browsers-and-drivers-compared-to-playwright-and-cypress">It’s too hard to set up browsers and drivers compared to Playwright and Cypress&lt;/h2>
&lt;p>This used to be true in the past as you had to download the drivers. This wasn’t too bad for GeckoDriver and SafariDriver as they could handle browser upgrades gracefully. On the other hand, you need to update the drivers for Chromium-based browser for every new release.&lt;/p>
&lt;p>For over a year now, Selenium handles this automatically. If it can’t find a ChromeDriver or EdgeDriver, it will download it using &lt;a href="https://www.selenium.dev/blog/2022/introducing-selenium-manager/">Selenium Manager&lt;/a>. Since its first release it has improved a lot and it is now probably the best in class since the latest versions of Selenium will even download browsers if it can and use that. Compared to Playwright and Cypress you don’t need to update your dependency on Selenium to update browsers and drivers, you still use the same browsers as your customers, and switching versions becomes a breeze: you don’t also have to change the test framework you’re using. And, let&amp;rsquo;s not forget that it uses the browser that &lt;a href="https://developer.chrome.com/blog/chrome-for-testing/">Google recommends you use for testing&lt;/a>.&lt;/p>
&lt;h2 id="setting-up-a-test-runner-is-hard-work-where-playwright-and-cypress-have-it-built-in">Setting up a test runner is hard work where Playwright and Cypress have it built in…&lt;/h2>
&lt;p>Well… maybe? Setting up E2E test frameworks with Selenium isn’t as difficult as some might suggest. The hard part really is making sure that the driver is in the right place and we’ve solved that as discussed above. Once that’s done, Selenium’s approach allows you to use whichever test runner you’re most comfortable with. If you’d like a “batteries included” approach, with Selenium tightly integrated with the test runner, then one of the many projects that use Selenium, such as &lt;a href="https://www.selenium.dev/ecosystem/#frameworks">SeleniumBase, Nightwatch, Serenity, and so on&lt;/a>, might be the right tool for you.&lt;/p>
&lt;p>One thing to note is that Playwright is the only multi-language browser automation framework like Selenium. However, if you don’t use TypeScript or JavaScript you will still need to do the setup of the test runner yourself. Some testing frameworks have plugins that automatically set up the fixtures you might need. In the JavaScript/TypeScript space if you really need a built-in test runner there are downstream projects like NightwatchJS and tangential projects like WebdriverIO. Downstream projects use our libraries and tangential projects have their own libraries but still follow the WebDriver standard.&lt;/p>
&lt;h2 id="playwright-and-cypress-can-do-network-interception-and-allow-me-to-write-event-driven-code-unlike-selenium">Playwright and Cypress can do network interception and allow me to write event-driven code unlike Selenium&lt;/h2>
&lt;p>Selenium has been able to offer this since Selenium 4 came out. It’s so good that even &lt;a href="https://playwright.dev/docs/selenium-grid">Playwright suggest you use it for scaling your tests&lt;/a>. The Selenium Project won’t be removing this anytime soon as we are dependent on WebDriver BiDi specification being implemented for those features to replace them. Even then Selenium has a history of trying to make sure that upgrades don’t break anything without sufficient warning. It’s why each language provides high-level wrappers, such as the &lt;code>NetworkInterceptor&lt;/code>, that isolate your tests from the underlying technology being used.&lt;/p>
&lt;h2 id="summary">Summary&lt;/h2>
&lt;p>As we have seen from the above Selenium is still as good as the products out there. One thing that is different for Selenium from Cypress or Playwright is that we’re a volunteer-driven project and not commercially backed. Want to help us out? Why not write a blog post about how you’re using the features above or post on social media how these features make your lives easier?&lt;/p></description></item><item><title>Blog: Removal of AbstractEventListener + EventFiringWebDriver + WebDriverEventListener</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2023/java-removal-of-deprecated-events-classes/</link><pubDate>Fri, 08 Dec 2023 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2023/java-removal-of-deprecated-events-classes/</guid><description>
&lt;h3 id="upgrading-to-webdriverlistener-and-eventfiringdecorator">Upgrading to WebDriverListener and EventFiringDecorator&lt;/h3>
&lt;p>Decorating the webdriver&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">EventFiringWebDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span> &lt;span style="color:#8f5902;font-style:italic">// Old approach
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">EventFiringDecorator&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">().&lt;/span>&lt;span style="color:#c4a000">decorate&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span> &lt;span style="color:#8f5902;font-style:italic">// New approach
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="implementing-method-wrappers">Implementing method wrappers&lt;/h3>
&lt;p>One may find the need to have their own custom implementations be used for underlying decorated method calls. An example may be wanting to use your own findElement implementation to store metadata from web elements. One can go down a deep rabbit hole of decorators ( extending WebDriverDecorator and such ), so to keep things simple we will extend EventFiringDecorator since we want a single decorator to handle all our listener events.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">WebDriverWrapper&lt;/span> &lt;span style="color:#204a87;font-weight:bold">implements&lt;/span> &lt;span style="color:#000">WebDriver&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">private&lt;/span> &lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">WebDriver&lt;/span> &lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">WebDriverWrapper&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">WebDriver&lt;/span> &lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">this&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">driver&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// custom implementation goes here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">By&lt;/span> &lt;span style="color:#000">by&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// custom implementation goes here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">by&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">testDecorator&lt;/span> &lt;span style="color:#204a87;font-weight:bold">extends&lt;/span> &lt;span style="color:#000">EventFiringDecorator&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">WebDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;gt;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#000">Object&lt;/span> &lt;span style="color:#000">call&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Decorated&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;?&amp;gt;&lt;/span> &lt;span style="color:#000">target&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Method&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Object&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[]&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#204a87;font-weight:bold">throws&lt;/span> &lt;span style="color:#000">Throwable&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">String&lt;/span> &lt;span style="color:#000">methodName&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">if&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;findElement&amp;#34;&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">equals&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">methodName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">))&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">WebDriverWrapper&lt;/span> &lt;span style="color:#000">newDriver&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">WebDriverWrapper&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">((&lt;/span>&lt;span style="color:#000">WebDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#000">target&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getOriginal&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">());&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">newDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">((&lt;/span>&lt;span style="color:#000">By&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">0&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#204a87;font-weight:bold">super&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">call&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">target&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Some notes about the above example, we are only overriding the ‘general’ call method and checking the method name against every call made.
Without going too deep decorators one can also override calls made by class instances to offer a more targeted approach.
Just to expose some more functionality, let&amp;rsquo;s modify our example.
We can modify WebElement context since we might care about child elements and elements found by WebDriver ( WebDriver and WebElement both extend the SearchContext ).&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">WebElementWrapper&lt;/span> &lt;span style="color:#204a87;font-weight:bold">implements&lt;/span> &lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">private&lt;/span> &lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#000">element&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">WebElementWrapper&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#000">element&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">this&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">element&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#000">element&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">By&lt;/span> &lt;span style="color:#000">by&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// custom implementation goes here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">element&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">by&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">WebElementDecorator&lt;/span> &lt;span style="color:#204a87;font-weight:bold">extends&lt;/span> &lt;span style="color:#000">EventFiringDecorator&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">WebDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;gt;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#000">Decorated&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">WebElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;gt;&lt;/span> &lt;span style="color:#000">createDecorated&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#000">original&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">DefaultDecorated&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&amp;gt;(&lt;/span>&lt;span style="color:#000">original&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#204a87;font-weight:bold">this&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#000">Object&lt;/span> &lt;span style="color:#000">call&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Method&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Object&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[]&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#204a87;font-weight:bold">throws&lt;/span> &lt;span style="color:#000">Throwable&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">String&lt;/span> &lt;span style="color:#000">methodName&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">if&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;findElement&amp;#34;&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">equals&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">methodName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">))&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// custom implementation goes here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span> &lt;span style="color:#000">WebElementWrapper&lt;/span> &lt;span style="color:#000">element&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">WebElementWrapper&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">getOriginal&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">());&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">element&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">((&lt;/span>&lt;span style="color:#000">By&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">0&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#204a87;font-weight:bold">super&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">call&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">};&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In the sample above, we are still doing a very similar approach of overriding the call method but now we are also targeting WebElement instances.&lt;/p>
&lt;h3 id="registering-listeners">Registering Listeners&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">EventFiringWebDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">).&lt;/span>&lt;span style="color:#c4a000">register&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">listener1&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">).&lt;/span>&lt;span style="color:#c4a000">register&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">listener2&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span> &lt;span style="color:#8f5902;font-style:italic">// Old approach
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">EventFiringDecorator&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">listener1&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">listener2&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span> &lt;span style="color:#8f5902;font-style:italic">// New approach
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="listening-to-events">Listening to Events&lt;/h3>
&lt;p>A quality of life change that is featured in WebDriverListener class is the use of ‘default’.
In Java, the &lt;code>default&lt;/code> keyword, when used in the context of an interface method, indicates that the method has a default implementation.
If a class implementing the interface chooses not to override the method, it will inherit the default implementation.
This change allows for splitting up listeners without needing to implement the unnecessary methods you don&amp;rsquo;t need or care about.&lt;/p>
&lt;h4 id="listening-to-specific-events-using-beforeafter-methods-call">Listening to specific events using before/after methods call&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// Old approach
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">AlertListener&lt;/span> &lt;span style="color:#204a87;font-weight:bold">implements&lt;/span> &lt;span style="color:#000">WebDriverEventListener&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">beforeAlertAccept&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">WebDriver&lt;/span> &lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// custom implementation goes here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// implement every method in interface
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// New approach
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">AlertListener&lt;/span> &lt;span style="color:#204a87;font-weight:bold">implements&lt;/span> &lt;span style="color:#000">WebDriverListener&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">beforeAccept&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Alert&lt;/span> &lt;span style="color:#000">alert&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// custom implementation goes here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// does not need to implement every method in interface
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="listening-to-generic-events">Listening to Generic Events&lt;/h4>
&lt;p>A change that was brought on is the ability to listen to generic events.
One use case is logging information in a parallelized test suite.
Rather than create a listener and override every method to add a simple log statement, there is now a simpler alternative of overriding one method call.
Below I override beforeAnyCall, but afterAnyCall exists as well which also has the results of the call to the decorated method.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">Listener&lt;/span> &lt;span style="color:#204a87;font-weight:bold">implements&lt;/span> &lt;span style="color:#000">WebDriverEventListener&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">private&lt;/span> &lt;span style="color:#204a87;font-weight:bold">static&lt;/span> &lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">Logger&lt;/span> &lt;span style="color:#000">LOGGER&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#000">Logger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getLogger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Listener&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">());&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">beforeAnyCall&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Object&lt;/span> &lt;span style="color:#000">target&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Method&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Object&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[]&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">logger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">debug&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Thread: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">Thread&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">currentThread&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">().&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">()&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4e9a06">&amp;#34; | Method Name: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">()&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4e9a06">&amp;#34; | Method Args: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">Arrays&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">toString&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>There also was an addition listening to more specific generic events.
Going back to the logging example, beforeAnyCall is a good method for debugging information or tracking the actions of a thread but might generate too much noise.
In the same use case we might only care about WebDriver or WebElement calls.
One can override instances of WebDriver and derived objects( WebElement, Alert, etc.) for before/after events.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">Listener&lt;/span> &lt;span style="color:#204a87;font-weight:bold">implements&lt;/span> &lt;span style="color:#000">WebDriverEventListener&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">private&lt;/span> &lt;span style="color:#204a87;font-weight:bold">static&lt;/span> &lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">Logger&lt;/span> &lt;span style="color:#000">LOGGER&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#000">Logger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getLogger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Listener&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">());&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">beforeAnyWebDriverCall&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">WebDriver&lt;/span> &lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Method&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Object&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[]&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">logger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">debug&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Thread: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">Thread&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">currentThread&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">().&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">()&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4e9a06">&amp;#34; | Method Name: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">()&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4e9a06">&amp;#34; | Method Args: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">Arrays&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">toString&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">beforeAnyWebElementCall&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#000">element&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Method&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Object&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[]&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">logger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">debug&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Thread: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">Thread&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">currentThread&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">().&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">()&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4e9a06">&amp;#34; | Method Name: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">()&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4e9a06">&amp;#34; | Method Args: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">Arrays&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">toString&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>So that&amp;rsquo;s some general examples on how to transition your code!
Happy testing!&lt;/p></description></item><item><title>Blog: InvalidSelectorException has changed</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2023/invalid-selector-exception-has-changed/</link><pubDate>Fri, 21 Apr 2023 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2023/invalid-selector-exception-has-changed/</guid><description>
&lt;p>Before Selenium 4.8.2 in Java and C#, when an invalid locator was used to identify an element, the resulting behavior would be
inconsistent in our bindings.&lt;/p>
&lt;p>For example, let&amp;rsquo;s check the following code:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">ArrayList&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">Class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;?&lt;/span> &lt;span style="color:#204a87;font-weight:bold">extends&lt;/span> &lt;span style="color:#000">Exception&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;gt;&amp;gt;&lt;/span> &lt;span style="color:#000">expectedExceptions&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">ArrayList&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&amp;gt;();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">expectedExceptions&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">add&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">org&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">openqa&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">selenium&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">NoSuchElementException&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">expectedExceptions&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">add&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">org&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">openqa&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">selenium&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">StaleElementReferenceException&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">expectedExceptions&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">add&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">org&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">openqa&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">selenium&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">ElementNotInteractableException&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">expectedExceptions&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">add&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">org&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">openqa&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">selenium&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">InvalidElementStateException&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">FluentWait&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&amp;gt;(&lt;/span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">withTimeout&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Duration&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">ofMillis&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">ELEMENT_IDENTIFICATION_TIMEOUT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">pollingEvery&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Duration&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">ofMillis&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">ELEMENT_IDENTIFICATION_POLLING_DELAY&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">ignoreAll&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">expectedExceptions&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">until&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">nestedDriver&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">-&amp;gt;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">nestedDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">By&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">xpath&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;invalid-xpath&amp;#34;&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)).&lt;/span>&lt;span style="color:#c4a000">click&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">});&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The expected result &lt;em>before this change&lt;/em> would be that the driver waits until the timeout expires and then throw an &lt;code>InvalidSelectorException&lt;/code>.&lt;/p>
&lt;p>This doesn&amp;rsquo;t make much sense because a broken/invalid selector would never fix itself, and hence should throw immediately.&lt;/p>
&lt;p>This was discussed and agreed during the &lt;a href="https://www.selenium.dev/meetings/2022/tlc-08-17/#proposals">TLC meeting on August 17, 2022&lt;/a>,
and implemented through the pull request &lt;a href="https://github.com/SeleniumHQ/selenium/pull/11727">11727&lt;/a> and the following
&lt;a href="https://github.com/SeleniumHQ/selenium/commit/f28144eb72ae1df18f267a5250db6b9b41dc1fdc">commit&lt;/a>.&lt;/p>
&lt;p>With the changes mentioned above, an invalid selector will throw an &lt;code>InvalidSelectorException&lt;/code> immediately.&lt;/p>
&lt;p>Please note that this may have an impact on backwards compatibility if you are not expecting this exception to be thrown while
handling invalid locators.&lt;/p>
&lt;p>Stay tuned for updates by following &lt;a href="https://twitter.com/seleniumhq">SeleniumHQ&lt;/a>!&lt;/p>
&lt;p>Happy testing!&lt;/p></description></item><item><title>Blog: Year End Review 2022</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/end-of-year-review/</link><pubDate>Fri, 23 Dec 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/end-of-year-review/</guid><description>
&lt;p>It was an amazing year here at the Selenium project, and we wanted to remind you of some of the great things we accomplished.&lt;/p>
&lt;p>In terms of releases, we continued to build on top of Selenium 4 which was launched in October 2021.
This year we published
&lt;a href="https://github.com/SeleniumHQ/selenium/releases/tag/selenium-4.2.0">v4.2&lt;/a>,
&lt;a href="https://github.com/SeleniumHQ/selenium/releases/tag/selenium-4.3.0">v4.3&lt;/a>,
&lt;a href="https://www.selenium.dev/blog/2022/selenium-4-4-0-released/">v4.4&lt;/a>,
&lt;a href="https://www.selenium.dev/blog/2022/selenium-4-5-0-released/">v4.5&lt;/a>,
&lt;a href="https://www.selenium.dev/blog/2022/selenium-4-6-0-released/">v4.6&lt;/a>, and
&lt;a href="https://www.selenium.dev/blog/2022/selenium-4-7-0-released/">v4.7&lt;/a>.
These releases included improvements, bug fixes, removal of deprecated functionality, improved error handling,
updates of the underlying libraries, support for the latest Chrome DevTools
versions to keep you in sync with new browser releases, but also new features.&lt;/p>
&lt;p>We introduced the first (beta) version of the embedded
&lt;a href="https://www.selenium.dev/blog/2022/introducing-selenium-manager/">Selenium Manager&lt;/a>.
The purpose of this feature is to
help you manage your driver binaries without having to manually update them yourself each time a new version is released.
We also introduced observability in the Docker-Selenium images.
Another major new feature is native support for
&lt;a href="https://www.selenium.dev/documentation/webdriver/actions_api/wheel/">scrolling&lt;/a> in the Actions API.
But these are only some of the highlights of what we released. To get the details for each
language we support, you can check out their corresponding Changelog pages: &lt;a href="https://github.com/SeleniumHQ/selenium/blob/trunk/java/CHANGELOG">Java&lt;/a>,
&lt;a href="https://github.com/SeleniumHQ/selenium/blob/trunk/py/CHANGES">Python&lt;/a>, &lt;a href="https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES">Ruby&lt;/a>,
&lt;a href="https://github.com/SeleniumHQ/selenium/blob/trunk/javascript/node/selenium-webdriver/CHANGES.md">Javascript&lt;/a>,
&lt;a href="https://github.com/SeleniumHQ/selenium/blob/trunk/dotnet/CHANGELOG">DotNet&lt;/a>.&lt;/p>
&lt;p>In terms of events and gatherings, in July our Selenium India Conference took place, this time online. It kicked off with
an 8 talk pre-conference event, namely Selenium Lite. We then had a full day of workshops, followed by 2 days of conference.
We had over 50 speakers and over 800 participants from around the world. The talks focused on Selenium, the Selenium ecosystem,
automation, methodologies and best practices. In case you missed some of these talks, you can still watch them
&lt;a href="https://www.youtube.com/playlist?list=PL9Z-JgiTsOYRfoG_mcRBlTUIFPIknhQ6S">here&lt;/a>.&lt;/p>
&lt;p>We also held 2 test automation summits: one in
&lt;a href="https://www.eventbrite.com/e/test-automation-summit-san-francisco-tickets-484039263467">San Francisco&lt;/a> and one in
&lt;a href="https://www.selenium.dev/blog/2022/test-automation-summit/">Berlin&lt;/a>. During these workshops the participants,
together with some of the maintainers of frameworks from the Selenium ecosystem, built their Selenium based projects,
added tests, new features and fixed bugs. During the first summit the participants focused on the
&lt;a href="https://w3c.github.io/webdriver-bidi/">BiDi protocol&lt;/a>, while during the second one the focus was on
&lt;a href="https://appium.io/">Appium&lt;/a> and mobile automation.&lt;/p>
&lt;p>We are kicking off next year with a few surprises.
The &lt;a href="https://www.selenium.dev/blog/2022/seleniumconf-chicago-2023-update/">Selenium Conference in Chicago&lt;/a>
just announced the &lt;a href="https://seleniumconf.com/">Speaker Lineup&lt;/a>. Stay tuned for further details!&lt;/p>
&lt;p>&lt;strong>Many thanks to &lt;a href="https://www.selenium.dev/project/structure">everyone who has contributed to the Selenium project&lt;/a> for all their hard work this year!&lt;/strong>&lt;/p>
&lt;p>And special thanks to all of you who are using, following and supporting the Selenium project.&lt;/p>
&lt;p>From everyone here at SeleniumHQ, may you have the best holidays and an amazing new year. See you in 2023!&lt;/p></description></item><item><title>Blog: BELLATRIX Test Automation Framework for C# and JAVA</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/bellatrix-test-automation-framework/</link><pubDate>Wed, 16 Nov 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/bellatrix-test-automation-framework/</guid><description>
&lt;p>Over the last decade, a large ecosystem of Open Source projects has sprouted up around Selenium. Selenium is often used for automating web applications for testing purposes, but it does not include a testing framework.
Nowadays, Selenium Ecosystem initiatives try to give popularity to popular open-source test automation frameworks maintained by people outside of the core Selenium maintainers.
One of these frameworks is BELLATRIX, invented by &lt;a href="https://www.linkedin.com/in/angelovstanton/">Anton Angelov&lt;/a>. It has two versions - C# and Java.
A testing framework is an abstraction in which common code provides generic functionality (which can be selectively overridden) for testing different aspects of our applications- UI, API, security, performance, and many others.&lt;/p>
&lt;h2 id="bellatrix-test-automation-framework">BELLATRIX Test Automation Framework&lt;/h2>
&lt;p>The first version of &lt;strong>&lt;a href="https://bellatrix.solutions/">BELLATRIX&lt;/a>&lt;/strong> appeared on 26 December 2017. It was available only for C# initially, but written on the new back then .NET Core, allowing the framework to be used on all major operating systems (cross-platform).
One huge advantage of BELLATRIX is its cross-technology readiness. It allows you to write tests for different technologies such as Web, Mobile, Desktop, and API. In BELLATRIX, we strive for the API for all modules to be as identical as possible.&lt;/p>
&lt;p>The usage is simple. We suggest cloning BELLATRIX as a GIT sub-module. Then, any customizations, tests, and project-specific plug-ins should be placed in a project outside the BELLATRIX cloned repository. This way, you can quickly update to the latest version.&lt;/p>
&lt;p>&lt;a href="https://bellatrix.solutions/">&lt;strong>BELLATRIX official website, download and releases info&lt;/strong>&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://github.com/AutomateThePlanet/BELLATRIX">&lt;strong>BELLATRIX official C# GitHub Page&lt;/strong>&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://github.com/AutomateThePlanet/BELLATRIX-Java">&lt;strong>BELLATRIX official Java GitHub Page&lt;/strong>&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://docs.bellatrix.solutions/overview/">&lt;strong>BELLATRIX C# Documentation&lt;/strong>&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://docs.java.bellatrix.solutions/overview/">&lt;strong>BELLATRIX Java Documentation&lt;/strong>&lt;/a>&lt;/p>
&lt;p>Let&amp;rsquo;s investigate how easy it is to create your first test with BELLATRIX in 15 minutes. The sample will showcase how to create a very basic test login into a website:
&lt;figure class="img-responsive w-50">
&lt;img src="https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/bellatrix-test-automation-framework/login-form.png"/>
&lt;/figure>
&lt;/p>
&lt;ol>
&lt;li>Open the &lt;strong>BellatrixTestFramework.sln&lt;/strong>&lt;/li>
&lt;/ol>
&lt;figure class="img-responsive w-50">
&lt;img src="https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/bellatrix-test-automation-framework/open_the_sln.png"/>
&lt;/figure>
&lt;ol start="2">
&lt;li>Under the &lt;strong>starthere&lt;/strong> folder, find the project you prefer: web, mobile, desktop, API&lt;/li>
&lt;/ol>
&lt;figure class="img-responsive w-50">
&lt;img src="https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/bellatrix-test-automation-framework/bellatrix-projects-structure.png"/>
&lt;/figure>
&lt;ol start="3">
&lt;li>Open the &lt;strong>BellatrixLoginTest.cs&lt;/strong> file. There you will find a sample test automating the login.&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-csharp" data-lang="csharp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c4a000">[TestClass]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">LoginTestsMSTest&lt;/span> &lt;span style="color:#000;font-weight:bold">:&lt;/span> &lt;span style="color:#000">MSTest&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">WebTest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">override&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">TestInit&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">App&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Navigation&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Navigate&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;http://demos.bellatrix.solutions/my-account/&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c4a000">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c4a000"> [TestMethod]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">SuccessfullyLoginToMyAccount&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">var&lt;/span> &lt;span style="color:#000">userNameField&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000">App&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Components&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">CreateById&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">TextField&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;gt;(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;username&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">var&lt;/span> &lt;span style="color:#000">passwordField&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000">App&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Components&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">CreateById&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">Password&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;gt;(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;password&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">var&lt;/span> &lt;span style="color:#000">loginButton&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000">App&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Components&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">CreateByXpath&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">Button&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;gt;(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;//button[@name=&amp;#39;login&amp;#39;]&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">userNameField&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">SetText&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;info@yourverybusywebsite.com&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">passwordField&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">SetPassword&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;yourverysecretp4ssw0rd$&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">loginButton&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Click&lt;/span>&lt;span style="color:#000;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">var&lt;/span> &lt;span style="color:#000">myAccountContentDiv&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000">App&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Components&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">CreateByClass&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">Div&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;gt;(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;woocommerce-MyAccount-content&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">myAccountContentDiv&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ValidateInnerTextContains&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Hello John&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">var&lt;/span> &lt;span style="color:#000">logoutLink&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000">App&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Components&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">CreateByInnerTextContaining&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">Anchor&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;gt;(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Log out&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">logoutLink&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ValidateIsVisible&lt;/span>&lt;span style="color:#000;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">logoutLink&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Click&lt;/span>&lt;span style="color:#000;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>All available services are available through the main &lt;strong>App&lt;/strong> class. The &lt;strong>Components&lt;/strong> property provides various &lt;strong>Create&lt;/strong> methods for finding elements. They are generic, so you need to mention the type of the searched element. We have different elements because, for each of them, BELLATRIX offers various additional methods and assertions on top of native WebDriver methods.
The sample code uses MSTest as the default test framework, but by changing the attributes, it will also work out of the box for NUnit. Of course, you need to change the base class namespace too.&lt;/p>
&lt;h2 id="why-bellatrix">Why BELLATRIX?&lt;/h2>
&lt;p>Let&amp;rsquo;s quickly list some of the essential things the framework brings to the table:&lt;/p>
&lt;h3 id="multiple-test-environments-configuration">Multiple Test Environments Configuration&lt;/h3>
&lt;p>Every aspect of the framework can be controlled via a rich JSON configuration designed to work for many test environments. &lt;a href="https://docs.bellatrix.solutions/web-automation/control-browser/#configuration">&lt;strong>Web Project Configuration&lt;/strong>&lt;/a>.&lt;/p>
&lt;h3 id="customization">Customization&lt;/h3>
&lt;p>One of the hardest things to develop is to allow these generic frameworks to be extendable and customizable. Knowing how essential customization is, we utilize different ways to achieve it. The major one is about &lt;a href="https://bellatrix.solutions/features/web/extend-the-framework-to-fit-your-needs/">&lt;strong>writing your own plug-ins&lt;/strong>&lt;/a>.&lt;/p>
&lt;h3 id="test-reliability">Test Reliability&lt;/h3>
&lt;p>One of the biggest problems in test automation is handling timeouts and performing actions on elements that may not be on the page right now. BELLATRIX hides the complexity of searching and &lt;a href="https://bellatrix.solutions/features/web/boost-test-reliability/">&lt;strong>waiting for elements&lt;/strong>&lt;/a>. Furthermore, when you perform an action or assertion against an element, we guarantee that once returned, it will be present.&lt;/p>
&lt;p>A significant part of your tests are the assertions - checking whether some conditions are met. To handle such scenarios, we created elements &lt;strong>Validate&lt;/strong> methods. They internally handle the whole complexity of waiting for some condition to happen.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-csharp" data-lang="csharp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">updateCart&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ValidateIsDisabled&lt;/span>&lt;span style="color:#000;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">totalSpan&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ValidateInnerTextIs&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;120.00€&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">timeout&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">30&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">sleepInterval&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">2&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">messageAlert&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ValidateIsNotVisible&lt;/span>&lt;span style="color:#000;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="complex-controls">Complex Controls&lt;/h3>
&lt;p>BELLATRIX provides API that makes handling HTML tables and grids much easier &lt;strong>&lt;a href="https://docs.bellatrix.solutions/web-automation/complex-components/">HTML tables and grids&lt;/a>&lt;/strong>.
&lt;figure class="img-responsive w-50">
&lt;img src="https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/bellatrix-test-automation-framework/grid-html-example.png"/>
&lt;/figure>
Here is an example for asserting grid cells:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-csharp" data-lang="csharp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">TestGrid&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ForEachCell&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">cell&lt;/span> &lt;span style="color:#000;font-weight:bold">=&amp;gt;&lt;/span> &lt;span style="color:#000">cell&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">AssertFontSize&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;14px&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">TestGrid&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">GetCell&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Firstname&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">1&lt;/span>&lt;span style="color:#000;font-weight:bold">).&lt;/span>&lt;span style="color:#000">ValidateInnerTextIs&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Mary&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">TestGrid&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">GetCell&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">0&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">1&lt;/span>&lt;span style="color:#000;font-weight:bold">).&lt;/span>&lt;span style="color:#000">ValidateInnerTextIs&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;John&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">TestGrid&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">GetCell&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">Employee&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;gt;(&lt;/span>&lt;span style="color:#000">cell&lt;/span> &lt;span style="color:#000;font-weight:bold">=&amp;gt;&lt;/span> &lt;span style="color:#000">cell&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">PersonalEmail&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">1&lt;/span>&lt;span style="color:#000;font-weight:bold">).&lt;/span>&lt;span style="color:#000">ValidateInnerTextIs&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;mary@hotmail.com&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>There is much more complex stuff that you can do with both components so check the &lt;strong>&lt;a href="https://docs.bellatrix.solutions/web-automation/complex-components/">official documentation&lt;/a>&lt;/strong>.&lt;/p>
&lt;h2 id="integrations">Integrations&lt;/h2>
&lt;p>Seamlessly integrate the framework with your existing tools and processes. Execute tests in the clouds, distribute and publish test results in reporting solutions. Maybe the most significant differentiators of the framework are its many integrations with popular tools such as Jira/qTest/Allure/ReportPortal and clouds such as AWS, Microsoft Azure, + many more. All these integrations leverage BELLATRIX plug-in architecture. For example, we have plug-ins for automatically generating/updating test cases based on our automated tests in qTest and AzureDevops or similarly creating automatic bug reports with steps to reproduce in Jira or Azure.&lt;/p>
&lt;h3 id="dynamic-test-cases">Dynamic Test Cases&lt;/h3>
&lt;p>Dynamic test cases are a unique feature in BELLATRIX, where the framework automatically generates test cases in a popular test case management system based on your automated tests. It will populate the title, description, and other necessary properties automatically. Moreover, it will generate human-readable steps and expected results. The most significant benefit is that it will keep up to date with your auto-generated test cases over time, no matter what you change in your tests. It is an excellent functionality which allows the non-technical people of your company to see what your tests are doing.&lt;/p>
&lt;h3 id="ai-validation-of-pdfs-and-image">AI Validation of PDFs and Image&lt;/h3>
&lt;p>Azure Computer Vision is a service that can be used to extract printed and handwritten text from images and documents with mixed languages and writing styles. In contrast, Azure Form Recognizer is an AI-powered document extraction service that understands your document.
You are not limited to PDFs only. You can use the same feature for extracting text from complex images. BELLATRIX comes with similar functionality based on the AWS cloud.&lt;/p>
&lt;h3 id="email-testing">Email Testing&lt;/h3>
&lt;p>BELLATRIX offers a few utilities for email testing. There are a few scenarios where we need such integration. The first one is related to creating unique email inboxes and using them to submit various online forms. Later, we can read the emails via the services and check the content of the emails. It might be enough to verify the content via regular C#, or in some cases, we might need to interact with the email content in the browser.&lt;/p>
&lt;p>There are tons of other integrations that we use on a daily basis in many big enterprise projects, such as cloud secrets management for securely storing credentials and other secrets.
&lt;strong>&lt;a href="https://docs.bellatrix.solutions/product-integrations/">All BELLATRIX Integrations&lt;/a>&lt;/strong>&lt;/p>
&lt;p>Using BELLATRIX in your projects might save months/years of effort even if you have the required programming knowledge. This way, you can quickly focus on writing automated tests for your project.
Usually, there are 4-6 major releases each year, including all bug fixes and new features. Check our &lt;strong>&lt;a href="https://bellatrix.solutions/roadmap/release-3-6-0-0-chamaeleon/">release notes history&lt;/a>&lt;/strong>. The framework is fully covered with over 4000 automated tests and offers rich documentation. We make sure to merge the new feature branches only when we are sure that everything is working. If some issue emerges after a major release, it is quickly fixed within a few days.&lt;/p>
&lt;p>For feature requests or bug reports, you can submit them to our GitHub repositories. If you believe that the functionality you developed can be added to the CORE framework or you have a bug fix, please submit a PR so we can discuss it and potentially merge it. For anything else, you can reach us via our &lt;strong>&lt;a href="https://bellatrix.solutions/contact-us/">contact us form&lt;/a>&lt;/strong>.&lt;/p></description></item><item><title>Blog: Dev and Beta Channel Browsers via Docker Selenium</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/dev-and-beta-channel-browsers-via-docker-selenium/</link><pubDate>Tue, 23 Aug 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/dev-and-beta-channel-browsers-via-docker-selenium/</guid><description>
&lt;p>The Docker Selenium browser Beta and Dev channel releases are now regularly published to &lt;a href="https://hub.docker.com/u/selenium">Docker Hub&lt;/a> and updated every two days. This enables testers and developers to test their applications on pre-release versions of Google Chrome, Mozilla Firefox, and Microsoft Edge before their official releases, using container tools, such as Docker. This empowers teams to stay ahead of the curve and catch potential showstoppers in their CI environment &lt;em>before&lt;/em> those issues have an impact on their users.&lt;/p>
&lt;h3 id="what-are-release-channels">What are &amp;ldquo;release channels&amp;rdquo;?&lt;/h3>
&lt;p>Here&amp;rsquo;s some background on release channels: Google, Mozilla, and Microsoft all maintain different &amp;ldquo;channels&amp;rdquo; for their respective browser releases. Most end users use the &amp;ldquo;Stable&amp;rdquo; channel. The Stable channel releases have passed rigorous testing, and these versions are considered &amp;ldquo;production-ready&amp;rdquo;. Up until now, this was the only option for a tester or developer when using Docker Selenium. Today, we&amp;rsquo;re pleased to announce teams can also test on versions of these browsers yet to be released to the general population. These are the Beta and Dev channels.&lt;/p>
&lt;p>For clarity, here is Google&amp;rsquo;s description of these 3 channels from &lt;a href="https://www.chromium.org/getting-involved/dev-channel/">their &amp;ldquo;Chrome Release Channels&amp;rdquo; page&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Stable channel:&lt;/strong> This channel has gotten the full testing and blessing of the Chrome test team, and is the best bet to avoid crashes and other issues. It&amp;rsquo;s updated roughly every two-three weeks for minor releases, and every 6 weeks for major releases.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>&lt;strong>Beta channel:&lt;/strong> If you are interested in seeing what&amp;rsquo;s next, with minimal risk, Beta channel is the place to be. It&amp;rsquo;s updated every week roughly, with major updates coming every six weeks, more than a month before the Stable channel will get them.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>&lt;strong>Dev channel:&lt;/strong> If you want to see what&amp;rsquo;s happening quickly, then you want the Dev channel. The Dev channel gets updated once or twice weekly, and it shows what we&amp;rsquo;re working on right now. There&amp;rsquo;s no lag between major versions, whatever code we&amp;rsquo;ve got, you will get. While this build does get tested, it is still subject to bugs, as we want people to see what&amp;rsquo;s new as soon as possible.&lt;/p>
&lt;/blockquote>
&lt;h3 id="standalone-usage">Standalone Usage:&lt;/h3>
&lt;p>To use these new Docker Selenium container images in Standalone mode, run the following commands:&lt;/p>
&lt;p>&lt;strong>Chrome Beta:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-chrome:beta
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Chrome Dev:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-chrome:dev
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Firefox Beta:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-firefox:beta
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Firefox Dev:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-firefox:dev
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Edge Beta:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-edge:beta
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Edge Dev:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-edge:dev
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="selenium-grid">Selenium Grid&lt;/h3>
&lt;p>To run these container images in a Selenium Grid, we&amp;rsquo;ll use docker-compose. For instance, this example shows how to run a Selenium Grid with Chrome, Firefox, and Edge on the Beta channel:&lt;/p>
&lt;p>&lt;strong>docker-compose-v3-beta-channel.yml:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic"># To execute this docker-compose yml file use `docker-compose -f docker-compose-v3-beta-channel.yml up`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic"># Add the `-d` flag at the end for detached execution&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic"># To stop the execution, hit Ctrl+C, and then `docker-compose -f docker-compose-v3-beta-channel.yml down`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>version: &lt;span style="color:#4e9a06">&amp;#34;3&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>services:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> chrome:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> image: selenium/node-chrome:beta
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shm_size: 2gb
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> depends_on:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> environment:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_HOST&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_PUBLISH_PORT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">4442&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_SUBSCRIBE_PORT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">4443&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> edge:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> image: selenium/node-edge:beta
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shm_size: 2gb
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> depends_on:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> environment:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_HOST&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_PUBLISH_PORT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">4442&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_SUBSCRIBE_PORT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">4443&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> firefox:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> image: selenium/node-firefox:beta
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shm_size: 2gb
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> depends_on:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> environment:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_HOST&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_PUBLISH_PORT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">4442&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_SUBSCRIBE_PORT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">4443&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> selenium-hub:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> image: selenium/hub:latest
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> container_name: selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ports:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#4e9a06">&amp;#34;4442:4442&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#4e9a06">&amp;#34;4443:4443&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#4e9a06">&amp;#34;4444:4444&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>To run on the more cutting edge &amp;ndash; and hence potentially more buggy &amp;ndash; Dev channel, simply replace the &amp;ldquo;beta&amp;rdquo; tags with &amp;ldquo;dev&amp;rdquo;.&lt;/p>
&lt;h3 id="support">Support&lt;/h3>
&lt;p>These Beta and Dev images represent pre-release browsers and WebDrivers, and they&amp;rsquo;re not guaranteed to be 100% stable. Should you run into any issues with these images, support from the Selenium community is limited and is dependent on the browser vendors. However, if you believe the issue is related to Selenium, please contact us in the &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/support/">various support channels&lt;/a>.&lt;/p></description></item><item><title>Blog: Scaling a Kubernetes Selenium Grid with KEDA</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/scaling-grid-with-keda/</link><pubDate>Fri, 19 Aug 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/scaling-grid-with-keda/</guid><description>
&lt;h2 id="the-issue">The Issue&lt;/h2>
&lt;p>If you have any experience with Selenium Grid and Kubernetes you will probably
run into an issue with scaling. Kubernetes (K8S) works wonders for scaling up and
down applications based on their CPU and Memory usage, but it is not so
straightforward when it comes down to applications like Selenium Grid.&lt;/p>
&lt;p>The issue is described quite well in &lt;a href="https://sahajamit.medium.com/spinning-up-your-own-auto-scalable-selenium-grid-in-kubernetes-part-2-15b11f228ed8">this blog post&lt;/a>.
But in short, the Horizontal Pod AutoScaler (HPA) that is built into
Kubernetes checks (by default) for resource consumption to determine
if a deployment needs to be scaled up or down. This becomes an issue
for Selenium Grid for a couple reasons:&lt;/p>
&lt;ol>
&lt;li>The browser pods use a variable amount of resources depending on
the demand of the current test. This means that all your browser pods
may be in use but there isn&amp;rsquo;t enough CPU usage for the HPA to decide
that a scale-up is needed, leaving tests waiting in the queue unnecessarily.&lt;/li>
&lt;li>When Kubernetes decides to scale down a deployment it does so
(for the most part) at random. You could have 10 tests running on
20 pods and need to scale down. More than likely at least one of
the pods asked to terminate will still have a test running, resulting
in connection failures.&lt;/li>
&lt;/ol>
&lt;h2 id="how-keda-helps">How KEDA Helps&lt;/h2>
&lt;p>&lt;a href="https://keda.sh/">KEDA&lt;/a> is a &lt;strong>free and open-source&lt;/strong> Kubernetes
event-driven autoscaling solution that extends the feature set of
K8S&amp;rsquo; HPA. This is done via plugins written by the community that
feed KEDA&amp;rsquo;s metrics server with the information it needs to scale
specific deployments up and down.&lt;/p>
&lt;p>Specifically for Selenium Grid, we have a &lt;a href="https://keda.sh/docs/latest/scalers/selenium-grid-scaler/">plugin&lt;/a>
that will tie into our grid to get the information it needs. Example of the used trigger:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">triggers&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>- &lt;span style="color:#204a87;font-weight:bold">type&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-grid&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">metadata&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">url&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;http://selenium-grid-url-or-ip:4444/graphql&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">browserName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;chrome&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>All of this gets saved as a Scaled-Object like so:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">apiVersion&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">keda.sh/v1alpha1&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">kind&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">ScaledObject&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">metadata&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">name&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-chrome-scaledobject&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">namespace&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">&amp;lt;namespace of your browser pods&amp;gt;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">labels&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">deploymentName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-chrome-node-deployment&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">spec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">minReplicaCount&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#0000cf;font-weight:bold">0&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">maxReplicaCount&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#0000cf;font-weight:bold">80&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">scaleTargetRef&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">name&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-chrome-node-deployment&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">triggers&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>- &lt;span style="color:#204a87;font-weight:bold">type&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-grid&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">metadata&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">url&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;https://selenium-grid-url-or-ip:4444/graphql&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">browserName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;chrome&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>As an added bonus KEDA allows us to scale our deployments down to
0 when there is no use, something the normal out-of-the-box HPA
does not allow.&lt;/p>
&lt;p>Check more details at &lt;a href="https://keda.sh/docs/latest/concepts/scaling-deployments/">the documentation for Scaled-Object in KEDA&lt;/a>.&lt;/p>
&lt;p>A full example of how to implement this is further down in the article
but KEDA solves one of our two issues. Now we can properly scale up and
down based on the actual load on the Selenium Grid. Unfortunately scaling
down still results in the likely possibility that a pod is still running
a test and is told to terminate before it can finish.&lt;/p>
&lt;h2 id="using-prestop-and-drain">Using PreStop and Drain&lt;/h2>
&lt;p>To combat this we are going to use a combination of K8s
&lt;a href="https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks">PreStop&lt;/a>
and Selenium Grid&amp;rsquo;s &lt;a href="https://www.selenium.dev/documentation/grid/advanced_features/endpoints/#drain-node">Drain&lt;/a>
functionality.&lt;/p>
&lt;ul>
&lt;li>&lt;code>PreStop&lt;/code> allows us to set a command or chain of commands that is run to completion before the container is told to stop.&lt;/li>
&lt;li>Drain tells the selenium browser pod to finish its current test and then shut down.&lt;/li>
&lt;/ul>
&lt;p>Together these look like so in our browser pod yaml:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">spec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">template&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">spec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">terminationGracePeriodSeconds&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#0000cf;font-weight:bold">3600&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">...&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">...&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">containers&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">lifecycle&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">preStop&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">exec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">command&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000;font-weight:bold">[&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;/bin/sh&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#34;-c&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#34;curl --request POST &amp;#39;localhost:5555/se/grid/node/drain&amp;#39; --header &amp;#39;X-REGISTRATION-SECRET;&amp;#39;; tail --pid=$(pgrep -f &amp;#39;[n]ode --bind-host false --config /opt/selenium/config.toml&amp;#39;) -f /dev/null; sleep 30s&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">]&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="breaking-this-down">Breaking this down&lt;/h4>
&lt;ul>
&lt;li>&lt;code>terminationGracePeriodSeconds&lt;/code> is set to however long you wish to give your
pods to gracefully terminate before being forced. In this case I give the pods
60 minutes to finish their test when asked to terminate. If you are also scaling
your cluster nodes as a part of this you may need to increase the termination
grace period for your cluster nodes as well.&lt;/li>
&lt;li>When the pod is told to stop, the &lt;code>PreStop&lt;/code> command is ran first.&lt;/li>
&lt;li>We curl the &lt;code>localhost&lt;/code> of our pod to tell it to drain. The pod will no
longer accept new session requests and will finish its current test. More
information on this &lt;a href="https://www.selenium.dev/documentation/grid/advanced_features/endpoints/#drain">can be found in the Selenium Grid documentation&lt;/a>.&lt;/li>
&lt;li>We then tail the internal node process that will continue to run until the node has been drained.&lt;/li>
&lt;li>After this we give the pod 30 seconds to finish anything else before giving the full termination command.&lt;/li>
&lt;/ul>
&lt;p>And with that our application can now safely scale down our selenium browser deployments!&lt;/p>
&lt;h2 id="from-start-to-finish">From Start to Finish&lt;/h2>
&lt;h3 id="install-keda">Install KEDA&lt;/h3>
&lt;ul>
&lt;li>You need to use version 2.8.0 or later, you can find the latest version number at the
&lt;a href="https://keda.sh/docs/latest/scalers/selenium-grid-scaler/">Selenium Grid Scaler docs&lt;/a>.&lt;/li>
&lt;li>&lt;code>kubectl apply -f https://github.com/kedacore/keda/releases/download/&amp;lt;Version_Number_Here&amp;gt;/keda-&amp;lt;Version_Number_Here&amp;gt;.yaml&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="create-and-apply-your-scaled-objects">Create and apply your scaled object(s)&lt;/h3>
&lt;p>As described earlier your &lt;a href="https://keda.sh/docs/latest/scalers/selenium-grid-scaler/">scaled object&lt;/a> will look like so:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">apiVersion&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">keda.sh/v1alpha1&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">kind&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">ScaledObject&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">metadata&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">name&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-chrome-scaledobject&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">namespace&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">&amp;lt;namespace of your browser pods&amp;gt;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">labels&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">deploymentName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-chrome-node-deployment&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">spec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">minReplicaCount&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#0000cf;font-weight:bold">0&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">maxReplicaCount&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#0000cf;font-weight:bold">80&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">scaleTargetRef&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">name&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-chrome-node-deployment&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">triggers&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>- &lt;span style="color:#204a87;font-weight:bold">type&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-grid&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">metadata&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">url&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;https://selenium-grid-url-or-ip:4444/graphql&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">browserName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;chrome&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You will need one of these for every browser you wish to scale.&lt;/p>
&lt;p>Things to edit:&lt;/p>
&lt;ol>
&lt;li>&lt;code>namespace&lt;/code> should be the namespace that your selenium browser pods exist in&lt;/li>
&lt;li>&lt;code>deploymentName&lt;/code> are the name of your browser deployment&lt;/li>
&lt;li>&lt;code>name&lt;/code> (within spec) is also the name of your browser deployment&lt;/li>
&lt;li>&lt;code>url&lt;/code> is the url of your selenium grid&lt;/li>
&lt;li>&lt;code>browserName&lt;/code> is the name of the browser you are using&lt;/li>
&lt;li>&lt;code>minReplicaCount&lt;/code> and &lt;code>maxReplicaCount&lt;/code> are the min and maximum pod count you want to have&lt;/li>
&lt;/ol>
&lt;p>If you plan to scale with Edge you will need at least version &lt;code>2.8.0&lt;/code> of KEDA and will
need to include &lt;code>sessionBrowserName&lt;/code> as well in the trigger metadata:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">triggers&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>- &lt;span style="color:#204a87;font-weight:bold">type&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">selenium-grid&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">metadata&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">url&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;https://selenium-grid-url-or-ip:4444/graphql&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">browserName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;MicrosoftEdge&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">sessionBrowserName&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#39;msedge&amp;#39;&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is due to a name change between the Edge sessions in the queue and the active
sessions and is &lt;a href="https://github.com/kedacore/keda/pull/3062">addressed through this pull request&lt;/a>.&lt;/p>
&lt;p>Once you have that ready just save it as a yaml file and apply with:&lt;/p>
&lt;ul>
&lt;li>&lt;code>kubectl apply -f ./&amp;lt;scaled-object-file-name&amp;gt;.yaml --namespace=&amp;lt;browser_namespace&amp;gt;&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="add-prestop-commands-to-your-browser-pods">Add PreStop commands to your browser pods&lt;/h3>
&lt;ol>
&lt;li>Set your &lt;code>terminationGracePeriodSeconds&lt;/code> of your deployment to whatever the maximum
time you wish to give the pods in order to terminate gracefully. Again you may need to
also increase the grace period for your nodepool as well which will vary depending on
your K8s provider.&lt;/li>
&lt;li>Add the &lt;code>PreStop&lt;/code> command to the container lifecycle spec:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">spec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">template&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">spec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">terminationGracePeriodSeconds&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#0000cf;font-weight:bold">3600&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">...&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000">...&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">containers&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">lifecycle&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">preStop&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">exec&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#204a87;font-weight:bold">command&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#000;font-weight:bold">[&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;/bin/sh&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#34;-c&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline"> &lt;/span>&lt;span style="color:#4e9a06">&amp;#34;curl --request POST &amp;#39;localhost:5555/se/grid/node/drain&amp;#39; --header &amp;#39;X-REGISTRATION-SECRET;&amp;#39;; tail --pid=$(pgrep -f &amp;#39;[n]ode --bind-host false --config /opt/selenium/config.toml&amp;#39;) -f /dev/null; sleep 30s&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">]&lt;/span>&lt;span style="color:#f8f8f8;text-decoration:underline">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>That is it, your Selenium Grid pods should now scale up and down properly without any lost sessions!&lt;/p></description></item><item><title>Blog: Test Automation Summit Berlin</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/test-automation-summit/</link><pubDate>Wed, 13 Jul 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/test-automation-summit/</guid><description>
&lt;p>Have you ever wanted to contribute to an open source testing project, but couldn&amp;rsquo;t figure out where to start?
If so, fill out &lt;a href="https://docs.google.com/forms/d/e/1FAIpQLSe6u6_bS59njqhhSwfnWSlGxlqQaNJ8xouDBR6YM-7pQYvJFQ/viewform">this form&lt;/a>
to apply for an invitation to join the Open Source Test Automation Summit on August 26 in Berlin,
sponsored by &lt;a href="https://www.selenium.dev">Selenium&lt;/a> and hosted by &lt;a href="https://saucelabs.com/">Sauce Labs&lt;/a>.
You can review the list of available projects below and select the one that you&amp;rsquo;d like to contribute to. We&amp;rsquo;ll be in touch soon if you
are selected to join us.
&lt;br/>&lt;/p>
&lt;p>&lt;strong>Update 7/22/2022:&lt;/strong>
Application deadline is July 28! We&amp;rsquo;ll contact everyone by Friday, July 29.&lt;/p>
&lt;figure class="img-responsive w-50">
&lt;img src="https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/test-automation-summit/TAS_Berlin.png"/>
&lt;/figure>
&lt;p>This will &lt;em>&lt;strong>not&lt;/strong>&lt;/em> be your typical workshop.
This will be a working session with one or more maintainers of a given project
to show you exactly what you need to know to contribute to that project.
Selected participants will be required to bring a laptop capable of executing Selenium tests,
including a working dev environment for the applicable programming language.&lt;/p>
&lt;p>This is a new idea we’re trying out, so space is very limited.
If there is sufficient demand we will consider doing more events like this in the future.&lt;/p>
&lt;h3 id="objectives">Objectives&lt;/h3>
&lt;p>At the end of the session you will be able to:&lt;/p>
&lt;ul>
&lt;li>Build the project on your computer&lt;/li>
&lt;li>Execute the existing test suite for the project&lt;/li>
&lt;li>Write new tests for the project&lt;/li>
&lt;li>Add a feature or fix a bug&lt;/li>
&lt;/ul>
&lt;h3 id="agenda-subject-to-change">Agenda (subject to change)&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Start&lt;/th>
&lt;th>End&lt;/th>
&lt;th>Activity&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>0900&lt;/td>
&lt;td>0930&lt;/td>
&lt;td>Breakfast&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>0930&lt;/td>
&lt;td>1000&lt;/td>
&lt;td>Talk: &amp;ldquo;State of WebDriver Ecosystem&amp;rdquo;&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>1000&lt;/td>
&lt;td>1100&lt;/td>
&lt;td>Lightning talks about participating projects&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>1100&lt;/td>
&lt;td>1200&lt;/td>
&lt;td>Split into working groups and walk through projects&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>1200&lt;/td>
&lt;td>1300&lt;/td>
&lt;td>Lunch&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>1300&lt;/td>
&lt;td>1630&lt;/td>
&lt;td>Continue with working sessions&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>1630&lt;/td>
&lt;td>1700&lt;/td>
&lt;td>Wrap up&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>1700&lt;/td>
&lt;td>&lt;/td>
&lt;td>Happy hour&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="participating-projects">Participating Projects&lt;/h3>
&lt;p>The following maintainers are will be present to assist you in working on their project:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Maintainer&lt;/th>
&lt;th>Project(s)&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;a href="https://twitter.com/asolntsev">Andrei Solntsev&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://selenide.org/">Selenide&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a href="https://twitter.com/boni_gg">Boni Garcia&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://github.com/bonigarcia/webdrivermanager">WebDriverManager&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a href="https://twitter.com/bromann">Christian Bromann&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://webdriver.io/">WebdriverIO&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a href="https://twitter.com/AutomatedTester">David Burns&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://wpt.fyi/results/webdriver/tests">W3C Web Platform Tests&lt;/a>, &lt;a href="https://www.selenium.dev/">Selenium&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a href="https://twitter.com/diegofmolina">Diego Molina&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://www.selenium.dev/">Selenium&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a href="https://www.linkedin.com/in/filip-cynarski-39b3b260/">Filip Cynarski&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://github.com/FluentLenium/FluentLenium">FluentLenium&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a href="https://twitter.com/JanMolak">Jan Molak&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://serenity-js.org/">Serenity/JS&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a href="https://www.linkedin.com/in/mikkonenjani/">Jani Mikkonen&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://robotframework.org/SeleniumLibrary/">Robot Framework&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a href="https://github.com/mykola-mokhnach">Nick Mokhnach&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://appium.io/">Appium&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a href="https://twitter.com/HtmlUnit">Ronald Brill&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://github.com/SeleniumHQ/htmlunit-driver">HTMLUnit Driver&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a href="https://twitter.com/shs96c">Simon Stewart&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://www.selenium.dev/">Selenium&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a href="https://twitter.com/titusfortner">Titus Fortner&lt;/a>&lt;/td>
&lt;td>&lt;a href="http://watir.com/">Watir&lt;/a>, &lt;a href="https://www.selenium.dev/">Selenium&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;a href="https://twitter.com/YevgenShunevych">Yevgeniy Shunevych&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://github.com/atata-framework/atata/">Atata&lt;/a>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Update 7/20/2022:&lt;/strong>
&lt;a href="https://twitter.com/HtmlUnit">Ronald Brill&lt;/a>, maintainer of
&lt;a href="https://github.com/SeleniumHQ/htmlunit-driver">HTMLUnit Driver&lt;/a> will now be joining us!&lt;/p>
&lt;p>&lt;strong>Update 7/25/2022:&lt;/strong>
&lt;a href="https://twitter.com/YevgenShunevych">Yevgeniy Shunevych&lt;/a>, maintainer of
&lt;a href="https://github.com/atata-framework/atata/">Atata&lt;/a> will now be joining us!&lt;/p>
&lt;p>&lt;strong>Update 7/26/2022:&lt;/strong> &lt;a href="https://twitter.com/shs96c">Simon Stewart&lt;/a>, creator of WebDriver, will now be joining us!&lt;/p>
&lt;h3 id="other-projects">Other Projects&lt;/h3>
&lt;p>Do you maintain an open source project in the WebDriver ecosystem?&lt;br>
Have you written a test framework that uses Selenium that is (or you want to make) open source?&lt;br>
Please fill out &lt;a href="https://docs.google.com/forms/d/e/1FAIpQLSdr21sc1j8a4yqq-TQnc6ATC4r7she2CuSSfZylvC_YOX3JFA/viewform">this form&lt;/a>
(provide additional relevant details in the comments), and we will be in touch about future events.&lt;/p></description></item><item><title>Blog: Removing Legacy Protocol Support</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/legacy-protocol-support/</link><pubDate>Fri, 20 May 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/legacy-protocol-support/</guid><description>
&lt;p>The Selenium team prides itself on how seriously it takes backwards compatibility.
A lot of care has gone into the Java bindings, especially, to ensure very few breaking changes over the years.
There is Selenium code written 15 years ago that can still run with Selenium 4 libraries!
Providing this exceptional amount of support comes with a large maintenance burden, though,
and we need to be able to properly meet the needs of the vast majority of our userbase.&lt;/p>
&lt;p>TL/DR:&lt;/p>
&lt;ul>
&lt;li>Support for the legacy &lt;a href="https://www.selenium.dev/documentation/legacy/json_wire_protocol/">JSON Wire Protocol&lt;/a>
will be removed from Java Selenium 4.9 (other languages have already removed this support)&lt;/li>
&lt;li>Protocol conversions will stop in Selenium 4.9 Grid&lt;/li>
&lt;li>You can ensure your sessions are W3C compliant by using
&lt;a href="https://www.selenium.dev/documentation/webdriver/getting_started/upgrade_to_selenium_4/#after">Browser Options classes&lt;/a>
instead of the deprecated Desired Capabilities classes (and avoid using &amp;ldquo;set capability&amp;rdquo; methods directly)&lt;/li>
&lt;li>If you rely on the current protocol conversion functionality, and it works for you,
you can continue to use it with Selenium Grid 4.8&lt;/li>
&lt;/ul>
&lt;p>By far the biggest challenge in the past seven years of Selenium development has been
transitioning the underlying implementation from the legacy &lt;a href="https://www.selenium.dev/documentation/legacy/json_wire_protocol/">JSON Wire Protocol&lt;/a>
to the new standardized &lt;a href="https://w3c.github.io/webdriver/">W3C WebDriver Protocol&lt;/a>.
Because the WebDriver specification was being actively developed at the time,
Selenium 3 supported both protocols simultaneously.
We implemented &amp;ldquo;handshake&amp;rdquo; code to determine which protocol to use.
When starting a session, Selenium would package the provided capabilities in both legacy and W3C formats,
send them to the driver/server, and use whichever protocol was returned.
This worked well for the most part. For many users, no changes were necessary to get
W3C compliant sessions from new browsers (Firefox 47+ and Chrome 75+).&lt;/p>
&lt;p>For the Java bindings, it was decided to take this approach one step further.
Instead of just sending along what was provided in both formats,
the code converted capabilities from the legacy protocol to the W3C protocol on behalf of the user.
The Selenium Grid makes use of this code, so, regardless of which client language sends legacy capabilities to it,
the Grid translates it to the W3C protocol for communication with the driver and then
re-translates the results back to the legacy protocol.
Because the code must make some assumptions and guesses for this to work, there are a lot of frustrating edge cases.&lt;/p>
&lt;p>For Selenium 4.0, the Ruby, JavaScript, and .NET bindings, each removed the handshake code,
so no legacy commands are used. Due to some issues that couldn&amp;rsquo;t be resolved before freezing the 3.x code,
Python is waiting until Selenium 4.9 to remove its handshake code.
The Selenium team intended to continue to support both protocols in the
Grid and Java bindings throughout the 4.x releases, but running test suites written for Selenium 2
on the Selenium 4 Grid resulted in a larger than expected number of failures.
Half a dozen bugs were discovered, some with a large effect.&lt;/p>
&lt;p>The code in question is sufficiently complex that fixing the bugs
without causing new problems would be a significant challenge.
As such, we’ve decided to start simplifying the code base again by explicitly
not supporting capabilities and commands from the legacy protocol in any of the Selenium codebase.
If you are using the latest version of Java Selenium, everything that will be removed
has already been marked deprecated, so double-check your usage to ensure there aren&amp;rsquo;t any surprises.&lt;/p>
&lt;p>If you’re interested in the nitty-gritty details of some of the issues we found
exploring this problem, you can look at the discussion in
&lt;a href="https://github.com/SeleniumHQ/selenium/issues/10374">Selenium Issue #10374&lt;/a>.&lt;/p>
&lt;p>For more information on ensuring compatibility with the Grid, please follow our
&lt;a href="https://www.selenium.dev/documentation/webdriver/getting_started/upgrade_to_selenium_4/">Selenium 4 Upgrade Guide&lt;/a>&lt;/p></description></item><item><title>Blog: Locate your locators - Python bindings changes upcoming</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/python-locators-se4/</link><pubDate>Tue, 01 Feb 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/python-locators-se4/</guid><description>
&lt;p>In real estate, the mantra for finding a new house or office space is
&amp;ldquo;location, location, location!&amp;rdquo;.
It could be said that when working with Selenium, a critical aspect of
writing tests is &amp;ldquo;locators, locators, locators!&amp;rdquo;.
Having a robust locator strategy - in your app under test and in
your test framework - is highly important for effective testing.&lt;/p>
&lt;p>If you are a Pythonista like myself and using Selenium for your test automation,
then there are some important changes coming to how locators are defined and used.&lt;/p>
&lt;p>Sometime after Selenium 4.2, the Python Selenium bindings will remove
locator-specific methods for finding elements. This means that the methods&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_id&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_id&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_name&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_name&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_tag_name&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_tag&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_css_selector&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_selector&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_class_name&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_class&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_link_text&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_text&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_partial_link_text&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_other_text&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_xpath&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_xpath&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>will be removed. All of these methods are in fact special cases of&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">By_object&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;some_locator&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>so this approach is now preferred (required, even) with the Python bindings.&lt;/p>
&lt;p>Note that it&amp;rsquo;s good practice to use the
&lt;a href="https://www.selenium.dev/selenium/docs/api/py/webdriver/selenium.webdriver.common.by.html#module-selenium.webdriver.common.by">By object&lt;/a>
which has specific values for using particular locator strategies. For example, this line&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_id&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;submit_button&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">click&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_css_selectors&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#39;.myelement child&amp;#39;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">text&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>becomes&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">By&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ID&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;submit_button&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">click&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">By&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">CSS_SELECTOR&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#39;.myelement child&amp;#39;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">text&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you&amp;rsquo;re really desperate however you can use strings instead of the By object:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#39;id&amp;#39;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;submit_button&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">click&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#39;css selector&amp;#39;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#39;.myelement child&amp;#39;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">text&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you have any plans to upgrade your Selenium client for your Python tests
to recent versions of Selenium 4, definitely keep these changes in mind.
It&amp;rsquo;s a good time to update your locator strategy and structure.&lt;/p>
&lt;p>(This article was originally posted
&lt;a href="https://simplythetest.tumblr.com/post/674917293614039040/locate-your-locators-python-bindings-changes">here&lt;/a>.
Thanks to the Selenium core contributors for adding this here!)&lt;/p></description></item><item><title>Blog: IE Mode in Edge supported by IEDriver</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/ie-edge-support/</link><pubDate>Tue, 18 Jan 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/ie-edge-support/</guid><description>
&lt;p>With the retirement of Internet Explorer 11 (IE 11) later this year, the folks in Redmond have helped the
Selenium project with getting IE Mode in Microsoft Edge working in IEDriver.&lt;/p>
&lt;p>IE 11 is due to retire on 15 June 2022 for certain versions of Windows 10. After this date, the Selenium project
recommends that you test your IE sites with IE Mode in Microsoft Edge. The Selenium Project will not remove
support for IE 11 when it retires but we will not actively fix issues as we have done with previous versions of IE.&lt;/p>
&lt;p>The Microsoft Edge team have committed to supporting IE Mode in Edge until 2029 when support for Windows 10 is retired.&lt;/p>
&lt;p>Microsoft have written up all the details on &lt;a href="https://techcommunity.microsoft.com/t5/windows-it-pro-blog/new-testing-tools-to-help-prepare-for-ie-retirement/ba-p/3059947">how to use and how to migrate your site&lt;/a>
and we recommend you go read and follow their steps to make sure you&amp;rsquo;re ready.&lt;/p></description></item><item><title>Blog: Improving &amp; refining our Docs translations</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/docs-translations/</link><pubDate>Fri, 03 Dec 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/docs-translations/</guid><description>
&lt;p>A while ago, we started to make the Selenium &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/documentation">documentation&lt;/a> available in more
languages. This, in an effort to offer a more inclusive environment for Selenium users who do
not have English as their mother tongue.&lt;/p>
&lt;p>This effort grew organically, and we got many pull requests adding content for different
languages. Over time, some translations got to a very good state, and others didn&amp;rsquo;t get much
attention. This brought the situation where 9 different languages are available in the
documentation, but only a few add value to the readers.&lt;/p>
&lt;p>To understand which languages are getting visits, we started using
&lt;a href="https://plausible.io">Plausible&lt;/a>. After a few weeks, we combined the information collected
by the analytics tool with the translated percentage per language, and we got the following:&lt;/p>
&lt;p>Here&amp;rsquo;s the number of visitors on the landing page for a given translation in the past 2 weeks,
and the percent of documentation pages translated:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Language&lt;/th>
&lt;th>Visitors&lt;/th>
&lt;th>Translated&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>ja&lt;/td>
&lt;td>1,700&lt;/td>
&lt;td>86%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>zh-cn&lt;/td>
&lt;td>1,500&lt;/td>
&lt;td>86%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>es&lt;/td>
&lt;td>409&lt;/td>
&lt;td>42%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>fr&lt;/td>
&lt;td>203&lt;/td>
&lt;td>31%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>pt-br&lt;/td>
&lt;td>189&lt;/td>
&lt;td>87%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>de&lt;/td>
&lt;td>88&lt;/td>
&lt;td>65%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ko&lt;/td>
&lt;td>79&lt;/td>
&lt;td>68%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>nl&lt;/td>
&lt;td>22&lt;/td>
&lt;td>6%&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>This shows that the most used languages (aside from English) are Japanese and Chinese, and that
the language that has translated most of the content is Portuguese.&lt;/p>
&lt;p>Based on this data, we decided to create a new role in the Selenium project:
&lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/project/structure/#docs_site_translators">translators&lt;/a>. This role will help the project
keep in shape the different translations available. Together with that, we are also putting
on hold the other available translations until we find volunteers for each language.&lt;/p>
&lt;p>If you have any questions or comments, please reach out through any of all the available options
shown at our &lt;a href="https://www.selenium.dev/support/">support page&lt;/a>.&lt;/p>
&lt;p>Stay tuned for updates by following &lt;a href="https://twitter.com/seleniumhq">SeleniumHQ&lt;/a>!&lt;/p>
&lt;p>Happy testing!&lt;/p></description></item><item><title>Blog: Stepping Down, Stepping Up</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/stepping-down-stepping-up/</link><pubDate>Wed, 27 Oct 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/stepping-down-stepping-up/</guid><description>
&lt;p>The short version is that I&amp;rsquo;m stepping down as the Selenium project
lead, and will concentrating on pushing WebDriver Bidi
forwards. Fortunately, the &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/project/structure/#tlc">Selenium TLC&lt;/a> have already been
steering the project for a while now, so it&amp;rsquo;s in excellent hands. With
Selenium 4 now shipped, the project has a new energy and enthusiasm
about it. The future is bright, and I&amp;rsquo;m looking forward to seeing what
it holds.&lt;/p>
&lt;p>The longer version? Well, that&amp;rsquo;s more personal. Let me start at the
beginning&amp;hellip;.&lt;/p>
&lt;p>On the 3rd January, 2007 I pushed the &lt;a href="https://github.com/SeleniumHQ/selenium/commit/29393a759063a0ea7a2d05c9592d687c4b6438a9">initial commit&lt;/a> of
&amp;ldquo;WebDriver&amp;rdquo; to a public repo. I helped with the Selenium 1.0 release,
and at the same time made sure that WebDriver emulated the original
Selenium RC APIs (in code that lives on to this day). In 2009, &lt;a href="https://twitter.com/hugs">Jason
Huggins&lt;/a> and I &lt;a href="https://youtu.be/Vlz-WmcrBL8">merged the Selenium and WebDriver
projects&lt;/a>, and I took over the leadership of the
project. I&amp;rsquo;ve been the lead for every version of Selenium since then,
often being the person who tagged each release in source control, all
the way up to the recent Selenium 4 release.&lt;/p>
&lt;p>By the numbers, that&amp;rsquo;s&lt;/p>
&lt;ul>
&lt;li>14 years of WebDriver&lt;/li>
&lt;li>12 years of Selenium for me
&lt;ul>
&lt;li>Though the first Selenium commits were in 2004&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>1 &lt;a href="https://www.thoughtworks.com/en-gb/insights/blog/happy-10th-birthday-selenium">10 year birthday celebration&lt;/a>&lt;/li>
&lt;li>Approximately 130 Selenium releases.&lt;/li>
&lt;li>I&amp;rsquo;ve landed just over 5100 commits
&lt;ul>
&lt;li>Which is about 20% of all the changes made to Selenium over the
years.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>3 different source control systems&lt;/li>
&lt;li>5 build systems&lt;/li>
&lt;li>14 Selenium conferences&lt;/li>
&lt;li>696 different people contributing to the project.&lt;/li>
&lt;/ul>
&lt;p>In a way, I blame Michael C for this. He and I worked together at
ThoughtWorks in Australia, and had been working with
&lt;a href="http://httpunit.sourceforge.net">HttpUnit&lt;/a>. My assertion was that its API was fine. His was
that it should be more &lt;a href="https://en.wikipedia.org/wiki/Object-oriented_programming">Object-Oriented&lt;/a>. To explore the idea, I
started writing an OO wrapper around HttpUnit, and (of course!)
Michael was right.&lt;/p>
&lt;p>Or maybe it&amp;rsquo;s &lt;a href="https://github.com/joewalnes">Joe Walnes&lt;/a> who I should be talking
about. At about the same, he&amp;rsquo;d been exploring a similar kind of
design, but where my API had a &lt;code>Browser&lt;/code>, his had the far better
sounding &lt;code>WebDriver&lt;/code>, and he was generous enough to allow me to use
the same name in my next iteration of the idea.&lt;/p>
&lt;p>Or, perhaps, it&amp;rsquo;s &lt;a href="https://paulhammant.com">Paul Hammant&lt;/a> and &lt;a href="https://www.thoughtworks.com">ThoughtWorks&lt;/a>. Paul was the
one who suggested Open Sourcing what was then &amp;ldquo;WebDriver&amp;rdquo; under the
Apache 2 license, and ThoughtWorks supported the decision to make the
code available to the world.&lt;/p>
&lt;p>In any case, on that day in 2007, I was sitting on the sofa with a
glass of red wine, creating the project on &lt;a href="https://code.google.com/archive/">Google Code&lt;/a>,
and thinking (if I was thinking deeply at all) that it&amp;rsquo;d be nice to
get the code out there, and in six months it&amp;rsquo;ll probably be
over. There was absolutely no way I could dream that the project would
grow far beyond me, emerging from the &lt;a href="https://www.nhm.ac.uk/discover/news/2019/february/the-cambrian-explosion-was-far-shorter-than-thought.html">Cambrian explosion&lt;/a>
of the early days of web testing to become first an industry-wide de
facto standard, and then, through the work done in the W3C, an &lt;a href="https://w3c.github.io/webdriver/">actual
standard&lt;/a>. It&amp;rsquo;s the only browser automation API that all the
browser vendors support.&lt;/p>
&lt;p>During these past 14 years, Selenium has been one of the constants of
my life. I joke sometimes that I&amp;rsquo;ve known it longer than my wife and
my son, but is it a joke if it&amp;rsquo;s true?&lt;/p>
&lt;p>Why spend that much time and effort on Open Source? On something that
you give away for free? Because it&amp;rsquo;s just been so incredibly
rewarding. I&amp;rsquo;ve had a chance to meet people from all over the globe,
work with amazing people from a range of companies I&amp;rsquo;d never have a
chance of working with normally, learn and practice skills I wouldn&amp;rsquo;t
have had a chance to exercise, and to write code that makes people&amp;rsquo;s
lives just a little bit easier.&lt;/p>
&lt;p>Most importantly, Selenium has been the way that I&amp;rsquo;ve met some of the
best friends I have in my life. I&amp;rsquo;ve been very lucky.&lt;/p>
&lt;p>I&amp;rsquo;ve also been lucky to have met and been part of the Selenium
community. The conferences and meetups have been a fantastic way to
hear about how people are using the tool, and I am constantly
impressed by how inventive and thoughtful people can be. The
conversations I&amp;rsquo;ve had at those events have changed how I think about
all sorts of things, and not just code. The IRC and Slack channels are
vibrant and interesting places to be. There are folks who are there
regularly who I&amp;rsquo;ve never met in person, but who I feel I could count
as friends.&lt;/p>
&lt;p>Who knew that Open Source could be the source of so much that makes a
life bright?&lt;/p>
&lt;p>But today, I&amp;rsquo;m stepping down as the project lead, and will be away
from the project until summer, though (in the true spirit of this
project), I’m not sure which year.&lt;/p>
&lt;p>Why, if all I said above is true, am I stepping down?&lt;/p>
&lt;p>The major reason is that the things I like to do, and that I&amp;rsquo;m good
at, are not the things that the project needs right now. It would be
hubris to believe that no-one else could do as good a job,
particularly when I know how amazing so many people on the project
are.&lt;/p>
&lt;p>The other reason is that I&amp;rsquo;m tired. For the past 14 years, much of my
free time, as well as hours within work, has been spent working on
Selenium. There are other projects and interests I&amp;rsquo;d like to pour some
energy into (just ask me how my Turkish lessons are going!)&lt;/p>
&lt;p>In my absence, the project&amp;rsquo;s &amp;ldquo;&lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/project/structure/#tlc">Technical Leadership Committee&lt;/a>&amp;rdquo;
will continue to be setting the direction of the project. I&amp;rsquo;ve been
listening to the discussions about where the project can go: it&amp;rsquo;s
going to be brilliant.&lt;/p>
&lt;p>That is, while I&amp;rsquo;m stepping down, the rest of the TLC will be stepping
up. They&amp;rsquo;ve already been running the project for a while. They’ll
continue the work we’ve started and carry it forwards and upwards. If
you&amp;rsquo;re reading this, and want to get involved, step in and &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/support/#ChatRoom">join the
fun&lt;/a>. Now&amp;rsquo;s the perfect time.&lt;/p>
&lt;p>When I took over as lead of the Selenium project, Paul joked that he
had thrown me the keys and run in the opposite direction. I guess it’s
my turn to do that now!&lt;/p>
&lt;p>Before finishing, I&amp;rsquo;d just like to say a heartfelt &amp;ldquo;thank you&amp;rdquo; to
everyone who&amp;rsquo;s been involved in the Selenium project. To everyone
who&amp;rsquo;s contributed in some way, or used the code we&amp;rsquo;ve written, thank
you. To everyone who&amp;rsquo;s filed a bug, thank you too. To all the people
who I&amp;rsquo;ve had the pleasure of so many conversations with, that I would
never have met without Selenium, thank you. To my family, who’ve
supported me and understood with endless patience that Selenium is a
part of our lives, thank you. And to my friends on the project, an
extra meaningful thank you.&lt;/p>
&lt;p>I won&amp;rsquo;t be here, but I won&amp;rsquo;t be far. See you all soon.&lt;/p></description></item><item><title>Blog: Selenium 4 Release Candidate</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/selenium-4-rc-1/</link><pubDate>Mon, 06 Sep 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/selenium-4-rc-1/</guid><description>
&lt;p>We&amp;rsquo;re very happy to announce the first release candidate of Selenium
4. We&amp;rsquo;re shipping this for .Net, Java, Python, Ruby, and JavaScript,
so if you&amp;rsquo;re using any of those languages, go and grab it from your
package manager of choice!&lt;/p>
&lt;p>This release is the result of a lot of work by the Selenium team
project, but most importantly, all the Selenium community who
tried our beta releases, and gave us great and valuable feedback.&lt;/p>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">&lt;a href="https://twitter.com/hashtag/Selenium?src=hash&amp;amp;ref_src=twsrc%5Etfw">#Selenium&lt;/a> 4 Release Candidate for &lt;a href="https://twitter.com/hashtag/ruby?src=hash&amp;amp;ref_src=twsrc%5Etfw">#ruby&lt;/a> is now available! There should be fewer problems running against latest versions of browsers now than with Selenium 3. Please update and let us know of any problems so we can get the production release out the door. &lt;a href="https://t.co/JWbwDRPcj4">https://t.co/JWbwDRPcj4&lt;/a>&lt;/p>&amp;mdash; Titus Fortner (@titusfortner) &lt;a href="https://twitter.com/titusfortner/status/1433114357047627785?ref_src=twsrc%5Etfw">September 1, 2021&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">So, big news: &lt;a href="https://twitter.com/hashtag/Selenium?src=hash&amp;amp;ref_src=twsrc%5Etfw">#Selenium&lt;/a> 4.0 RC1 has just been released! The .NET bindings are available via &lt;a href="https://twitter.com/hashtag/NuGet?src=hash&amp;amp;ref_src=twsrc%5Etfw">#NuGet&lt;/a>, or you can find them at our new binary release point, &lt;a href="https://t.co/CSNK7K47ue">https://t.co/CSNK7K47ue&lt;/a>. We&amp;#39;re closing in on a final, stable 4.0 release, so if you haven&amp;#39;t tried it before now, you should!&lt;/p>&amp;mdash; Jim Evans (@jimevansmusic) &lt;a href="https://twitter.com/jimevansmusic/status/1433140517819322369?ref_src=twsrc%5Etfw">September 1, 2021&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">&lt;a href="https://twitter.com/hashtag/Selenium?src=hash&amp;amp;ref_src=twsrc%5Etfw">#Selenium&lt;/a> 4 RC1 is out! The &lt;a href="https://twitter.com/hashtag/python?src=hash&amp;amp;ref_src=twsrc%5Etfw">#python&lt;/a> bindings are available at &lt;a href="https://t.co/B4zKI6JQkA">https://t.co/B4zKI6JQkA&lt;/a> &lt;a href="https://t.co/kMlDM4ad7I">pic.twitter.com/kMlDM4ad7I&lt;/a>&lt;/p>&amp;mdash; David @automatedtester@mastodon.social (@AutomatedTester) &lt;a href="https://twitter.com/AutomatedTester/status/1433377616065667074?ref_src=twsrc%5Etfw">September 2, 2021&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">Hurrah! &lt;a href="https://twitter.com/hashtag/selenium4?src=hash&amp;amp;ref_src=twsrc%5Etfw">#selenium4&lt;/a> RC1 is out, and the Java bindings have been released! Grab them from your favourite maven repo, or download the binaries from &lt;a href="https://t.co/XUcv7RzbzL">https://t.co/XUcv7RzbzL&lt;/a> &lt;a href="https://t.co/E9T1ZTZ9jd">pic.twitter.com/E9T1ZTZ9jd&lt;/a>&lt;/p>&amp;mdash; Simon Mavi Stewart (@shs96c) &lt;a href="https://twitter.com/shs96c/status/1433474873972641793?ref_src=twsrc%5Etfw">September 2, 2021&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">&lt;a href="https://twitter.com/SeleniumHQ?ref_src=twsrc%5Etfw">@SeleniumHQ&lt;/a> 4 RC 1 is out! This means that Selenium 4 is getting closer and closer 🎉🎉&lt;br>Try out the new Grid through our &lt;a href="https://twitter.com/Docker?ref_src=twsrc%5Etfw">@docker&lt;/a> images -&amp;gt; &lt;a href="https://t.co/lGUrZAQneJ">https://t.co/lGUrZAQneJ&lt;/a> &lt;a href="https://t.co/BzZxPn3p0y">pic.twitter.com/BzZxPn3p0y&lt;/a>&lt;/p>&amp;mdash; Diego Molina (@diegofmolina) &lt;a href="https://twitter.com/diegofmolina/status/1434820167360339968?ref_src=twsrc%5Etfw">September 6, 2021&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;p>One thing you may want to do to get ready for the update (which you
can do before updating the dependency itself!) is to update the
drivers you need. In particular, please update &lt;a href="https://github.com/mozilla/geckodriver/releases">geckodriver&lt;/a> to
0.29.1 or later.&lt;/p>
&lt;p>Most of the new features in Selenium 4 are mentioned in this &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/what-is-coming-in-selenium-4-new-tricks/">blog entry&lt;/a>,
but the main highlights are:&lt;/p>
&lt;ul>
&lt;li>Relative locators, for finding elements using terms that make
sense to us humans.&lt;/li>
&lt;li>The ability to intercept network traffic&lt;/li>
&lt;li>Authentication with basic or digest authentication.&lt;/li>
&lt;/ul>
&lt;p>If this sounds interesting, please download the release candidate from your
favourite package manager (maven, nuget, npm, pip, or the gem), or
directly from the &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/downloads">Selenium site&lt;/a>.&lt;/p></description></item><item><title>Blog: All Selenium downloads are now available on GitHub releases</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/downloads-now-on-github-releases/</link><pubDate>Tue, 24 Aug 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/downloads-now-on-github-releases/</guid><description>
&lt;p>We announced on a previous &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/downloads-moving-to-github-releases/">entry&lt;/a> our
decision to move all binaries from &lt;a href="https://selenium-release.storage.googleapis.com/index.html">Google Storage&lt;/a>
to &lt;a href="https://github.com/SeleniumHQ/selenium/releases">GitHub releases&lt;/a>. Today, we would like to
announce that this work has been completed and all binaries are also available to be downloaded
in each one of the releases we have done in GitHub.&lt;/p>
&lt;p>In addition to that, all links on our &lt;a href="https://www.selenium.dev/downloads/">downloads&lt;/a> page
have been updated, as well as all references to Google Storage in the Selenium code base.&lt;/p>
&lt;p>Please note that all past releases will be available both in Google Storage and GitHub releases,
but new ones will only be present in GitHub releases. We recommend everyone to modify your
download scripts to keep all tooling up to date.&lt;/p>
&lt;p>If you have any questions or comments, please reach out through any of all the available options
shown at our &lt;a href="https://www.selenium.dev/support/">support page&lt;/a>.&lt;/p>
&lt;p>Stay tuned for updates by following &lt;a href="https://twitter.com/seleniumhq">SeleniumHQ&lt;/a>!&lt;/p>
&lt;p>Happy testing!&lt;/p></description></item><item><title>Blog: Selenium downloads will move to GitHub releases</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/downloads-moving-to-github-releases/</link><pubDate>Thu, 19 Aug 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/downloads-moving-to-github-releases/</guid><description>
&lt;p>Thanks to Google, &lt;a href="https://selenium-release.storage.googleapis.com/index.html">Google Storage&lt;/a>
has been the central place where we have been able to upload all binaries created for each
Selenium release, and the place where the Selenium community can download them from. To do so,
all people needed to do was visit our &lt;a href="https://www.selenium.dev/downloads/">downloads&lt;/a> page,
find the release, and download from there!&lt;/p>
&lt;p>The Selenium project hosts its source code on GitHub, and people who are familiar with GitHub
know that they can go to the &lt;a href="https://github.com/SeleniumHQ/selenium/releases">&amp;ldquo;release&amp;rdquo;&lt;/a> page
there to find any downloads for each release of a project.&lt;/p>
&lt;p>Rather than hosting the downloads in two places, the Selenium project has decided to host
everything on GitHub. We&amp;rsquo;ll still have links from the download page, but rather than pointing
to Google Storage, these will now point to the downloads for each corresponding release tagged
on GitHub.&lt;/p>
&lt;p>All past releases will be available both in Google Storage and GitHub releases, but new ones
will only be present in GitHub releases.&lt;/p>
&lt;p>If you are a watcher of the Selenium &lt;a href="https://github.com/SeleniumHQ/selenium">repo&lt;/a>, please note
that there will be some noise in your inboxes. We need to create releases for old tags in order
to upload the binaries to the release (as is the way GitHub releases work), and we expect to
complete this in the next couple of weeks.&lt;/p>
&lt;p>If you have any questions or comments, please reach out through any of all the available options
shown at our &lt;a href="https://www.selenium.dev/support/">support page&lt;/a>.&lt;/p>
&lt;p>Stay tuned for updates by following &lt;a href="https://twitter.com/seleniumhq">SeleniumHQ&lt;/a>!&lt;/p>
&lt;p>Happy testing!&lt;/p></description></item><item><title>Blog: The Selenium website has a new look!</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/new-look-for-selenium-site/</link><pubDate>Mon, 09 Aug 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/new-look-for-selenium-site/</guid><description>
&lt;p>We have been working hard during the last few weeks redoing our
&lt;a href="//selenium.dev">website&lt;/a>. Today, we are very happy to share it
with the community and we are hoping to get as much feedback as
possible!&lt;/p>
&lt;p>We did a major revamp to our website two years ago. However, this
revamp had some &amp;ldquo;technical debt&amp;rdquo; in it&amp;hellip;&lt;/p>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">We&amp;#39;re happy to announce that we have (finally!) refreshed our site. Head on over to &lt;a href="https://t.co/0xAiKdHrPj">https://t.co/0xAiKdHrPj&lt;/a> and have a browse! Thanks to &lt;a href="https://twitter.com/diegofmolina?ref_src=twsrc%5Etfw">@diegofmolina&lt;/a> and &lt;a href="https://twitter.com/manoj9788?ref_src=twsrc%5Etfw">@manoj9788&lt;/a> for making this happen.&lt;/p>&amp;mdash; Selenium (@SeleniumHQ) &lt;a href="https://twitter.com/SeleniumHQ/status/1194205732347887616?ref_src=twsrc%5Etfw">November 12, 2019&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;p>We use &lt;a href="https://gohugo.io/">Hugo&lt;/a> to generate our website, and to
build a website with Hugo, one normally needs to select a
&lt;a href="https://themes.gohugo.io/">Hugo theme&lt;/a>. Our previous website was
being built using two different Hugo themes, which was less than
ideal. Having two Hugo themes was hard to maintain and accepting
contributions was tricky in some cases.&lt;/p>
&lt;p>This new website version is using the &lt;a href="https://github.com/google/docsy">Docsy&lt;/a>
theme, made by some folks at Google and used by other popular projects
such as &lt;a href="https://airflow.apache.org/">Apache Airflow&lt;/a> and
&lt;a href="https://kubernetes.io/">Kubernetes&lt;/a>. Using Docsy helps us to focus
more on the website&amp;rsquo;s content rather than spending lots of time
maintaining the underlying details of it.&lt;/p>
&lt;p>We all hope you will like the new look and please check our
&lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/documentation/about/contributing/">contribution guidelines&lt;/a> if
you want to contribute to the Selenium website.&lt;/p>
&lt;p>Happy testing!&lt;/p></description></item><item><title>Blog: IRC channels are moving to Libera.chat</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/moving-to-libera-chat/</link><pubDate>Thu, 20 May 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/moving-to-libera-chat/</guid><description>
&lt;p>Yesterday, 19 May 2021, all the staff of Freenode, the IRC network, &lt;a href="https://fuchsnet.ch/freenode-resign-letter.txt">collectively
resigned as staff because of what they felt was a hostile takeover&lt;/a>.&lt;/p>
&lt;p>Freenode has always been seen as the home of Free and Open Software, so
it was natural that you could find us on the #selenium channel there. To maintain this openness, and inclusivity,
we are moving our IRC Channel over to &lt;a href="https://libera.chat">Libera.chat&lt;/a>. It is has been created
by the team that previously maintained Freenode.&lt;/p>
&lt;p>We are in the process of moving our Slack-to-IRC bridge over and hopefully the matrix bridge will be created
soon so that we can have a free and inclusive project on the new IRC Servers. There may be a few
hiccups so if you could bear with us.&lt;/p>
&lt;p>If you have any questions please feel free to reach out to me on &lt;a href="https://twitter.com/automatedtester">twitter&lt;/a>
or on one of the &lt;a href="https://selenium.dev/support">chat protocols&lt;/a> we support.&lt;/p>
&lt;p>Finally, thank you to &amp;ldquo;Milen from Bulgaria&amp;rdquo; for helping secure the channel for us on &lt;a href="https://libera.chat">Libera.chat&lt;/a>.&lt;/p></description></item><item><title>Blog: Selenium 4 Beta 1 Released</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/selenium-4-beta-1/</link><pubDate>Mon, 15 Feb 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/selenium-4-beta-1/</guid><description>
&lt;p>We&amp;rsquo;re very happy to announce the release of the first beta of Selenium
4. We&amp;rsquo;re shipping this for Java, .Net, Python, Ruby, and JavaScript,
so if you&amp;rsquo;re using any of those languages, go and grab it from your
package manager of choice!&lt;/p>
&lt;p>This has been the culmination of a lot of work by so many people, not
only the &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/structure/#tlc">project TLC&lt;/a>, but also of literally hundreds of people:
205 since we released Selenium 3.141.59, at the last count. A big
thank you to everybody who&amp;rsquo;s helped make this possible!&lt;/p>
&lt;p>So, what&amp;rsquo;s changed since Selenium 3? The answer is both &amp;ldquo;&lt;strong>not much&lt;/strong>&amp;rdquo;
and also &amp;ldquo;&lt;strong>almost everything&lt;/strong>&amp;rdquo;.&lt;/p>
&lt;p>By &amp;ldquo;&lt;strong>not much&lt;/strong>&amp;rdquo;, I mean that if your tests are working with Selenium
3 right now, you should be able to just upgrade your dependency to
Selenium 4. You will find that things that were marked &amp;ldquo;deprecated&amp;rdquo;
are now gone, but the advantage of the long time between the last
Selenium 3 release and this is that you&amp;rsquo;ve had plenty of time to try
and find alternatives.&lt;/p>
&lt;p>If this doesn&amp;rsquo;t work, please let us know! We&amp;rsquo;ve worked hard to ensure
compatibility between the releases, but it&amp;rsquo;s possible we may have
missed some things.&lt;/p>
&lt;p>One thing you may want to do to get ready for the update (which you
can do before updating the dependency itself!) is to update the
drivers you need. In particular, please update &lt;a href="https://github.com/mozilla/geckodriver/releases">geckodriver&lt;/a> to
0.29.0 or later.&lt;/p>
&lt;p>By &amp;ldquo;&lt;strong>almost everything&lt;/strong>&amp;rdquo;, I mean that under the covers there have
been substantial changes. We&amp;rsquo;ve rewritten the Selenium server to allow
it to work not only in the familiar &amp;ldquo;standalone&amp;rdquo; and &amp;ldquo;hub and node&amp;rdquo;
modes, but also in a new &amp;ldquo;distributed&amp;rdquo; mode, which makes it
signifcantly easier to deploy to something such as Kubernetes in a way
that scales well.&lt;/p>
&lt;p>The new server is also wired up with support for &lt;a href="https://opentelemetry.io">OpenTelemetry&lt;/a> and
exposes a &lt;a href="https://github.com/SeleniumHQ/selenium/blob/selenium-4.0.0-beta-1/java/server/src/org/openqa/selenium/grid/graphql/selenium-grid-schema.graphqls">GraphQL endpoint&lt;/a>, so that figuring what&amp;rsquo;s going
on in the Grid, and tracking down what&amp;rsquo;s gone wrong if something
happens, is easier than ever.&lt;/p>
&lt;p>Not all the changes are server-side. We recently wrote about the &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/what-is-coming-in-selenium-4-new-tricks/">new
features in Selenium 4&lt;/a> that you can use in your tests, but some
of the main highlights are:&lt;/p>
&lt;ul>
&lt;li>Relative locators, for finding elements using terms that make
sense to us humans.&lt;/li>
&lt;li>The ability to intercept network traffic&lt;/li>
&lt;li>Authentication with basic or digest authentication.&lt;/li>
&lt;/ul>
&lt;p>We&amp;rsquo;ll be telling you more about these features in later blog posts,
and as we improve our documentation.&lt;/p>
&lt;p>If this sounds interesting, please download the beta from your
favourite package manager (maven, nuget, npm, pip, or the gem), or
directly from the &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/downloads">Selenium site&lt;/a>.&lt;/p></description></item><item><title>Blog: New Tricks in Selenium 4</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/what-is-coming-in-selenium-4-the-new-selenium-grid/</link><pubDate>Fri, 05 Feb 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/what-is-coming-in-selenium-4-the-new-selenium-grid/</guid><description>
&lt;blockquote>
&lt;p>In the fourth and final post in his series, Simon Stewart continues talking about what&amp;rsquo;s
coming in Selenium 4 and reviews what&amp;rsquo;s new in the Selenium Grid.&lt;/p>
&lt;/blockquote>
&lt;p>We’ve covered a lot of ground in the past few blog posts, including how to contribute to the project, and some
details of what you can expect as a Selenium user. But there’s more to Selenium than just the APIs you use to write
your tests, and one of the big features we’ve not covered yet is the refreshed Selenium Grid: a mechanism that
allows you to distribute your tests across a fleet of machines.&lt;/p>
&lt;p>Before going further, it’s always nice to acknowledge where we’ve come from, not only because it’s interesting, but
also because it helps explain the “why” of the refreshed design.&lt;/p>
&lt;p>Way back in the mists of time (2008), Jennifer Bevin and Jason Huggins worked on a system called the Selenium Farm
at Google. This was a fleet of machines sitting in a cupboard somewhere that allowed you to run the original
Selenium protocol. This was, of course, at Google scale, so there was more than one cupboard :)&lt;/p>
&lt;p>This allowed people at Google to distribute their tests and scale out beyond their individual machines.
This was such a great idea that when Jennifer talked about the Farm at a Selenium meetup, Philippe
Haringou (then at ThoughtWorks) decided to write an Open Source implementation of the same thing,
which he called “Selenium Grid”.&lt;/p>
&lt;p>Selenium Grid was a lovely piece of technology, but it had one drawback: it only spoke the original
Selenium RC protocol. That was fine, but WebDriver spoke a different wire protocol, which was called the
JSON Wire Protocol, and folks wanted to be able to use both Selenium RC and WebDriver at the same time.&lt;/p>
&lt;p>This is where Francois Reynaud enters the picture. He was working at eBay, reporting to Michael Palotas,
and he had written something like the original Selenium Grid, but which also worked with the JSON Wire
Protocol. They very kindly contributed that work to the Selenium project, and it formed the basis of the
Selenium Grid 2. We decided at the time that the Selenium standalone server would effectively be a
“grid of one”: it would have everything you needed in it to set up a Selenium Grid, as well as to work as
a single standalone server. Merging the code and getting it stable took a while, but thanks to the efforts
of Francois, Kristian Rosenvold, and many others, we merged Grid 2 into the main Selenium project and shipped
Selenium 2 in 2011.&lt;/p>
&lt;p>Even if 2011 doesn’t feel that long ago, the modern world has changed quite significantly. In 2011, we didn&amp;rsquo;t
have Docker. We didn&amp;rsquo;t have Kubernetes, we didn&amp;rsquo;t really have AWS. So, the Selenium Grid didn&amp;rsquo;t know that those
things were coming in, and wasn&amp;rsquo;t written to take advantage of them. Fortunately, we did have virtual machines
back then, and the Grid 2 had been designed to be able to support them.&lt;/p>
&lt;p>This was the hook that an excellent project called Zalenium. Developed by Diego Molina, Zalenium added a really
nice UI and support for Docker and Kubernetes—all built on top of the Grid 2. This has allowed the Selenium Grid to
continue to be relevant and useful to this day, which is an amazing achievement.&lt;/p>
&lt;p>But, like I said, it took us time to stabilise Grid 2: about six months of hard work, largely led by Kristian.
That’s because while Grid 2 was sophisticated, the code was hard to read and hard to maintain—and very few people
could do that. Worse, the merging of the Grid 2 and the original Selenium server was pretty crude; effectively
there were two separate servers shipped in the same binary. This led to problems occurring in the Grid but not
when run in standalone mode, and vice versa.&lt;/p>
&lt;p>With Selenium 4 we’ve decided to bite the bullet and address these three concerns. Firstly, we want something that
was easier to work on and maintain. Secondly, we want to merge the servers into a single unit. Thirdly, we want
something that will take advantage of the world of modern infrastructure we have available to us now, not just in
the form of Docker and Kubernetes, but also to be able to use emerging technologies such as distributed tracing.&lt;/p>
&lt;p>To do this, we looked at the functionality the Grid provided, and to model each piece as a component that we can
either run “in memory” (allowing us to have a single standalone server), or in a more distributed way, allowing
the “hub and node” architecture that we’re familiar with from the original Selenium Grid, to a fully distributed
design.&lt;/p>
&lt;p>The first component is the “router”. It serves as the entry point to the Grid. You can expose it to the internet
and it directs requests to the Grid. It’s designed to be stateless, and so you can add more to Grid as you find
you need to.&lt;/p>
&lt;p>When the router sees a new session request, it places it on a “session queue.” The session queue is read by a
component called the “distributor,” which maintains a model of all the places in the Grid where a session could be
run: we call them “slots”. The slots are hosted by components called “nodes,” and each node can have one or more
slots. When the distributor pulls a new session request from the queue, it identifies the most appropriate slot
to use, and forwards the request to the node which owns the slot. Once the node has started the session, the
distributor puts the session ID and the URL of the Node that is running the test into the “session map”—you can
think of the session map as being a simple map of a session ID to URL—and the new session response is sent
back to the waiting test.&lt;/p>
&lt;p>Requests for running sessions (that is, for most webdriver calls!) are handled slightly differently. The router
will use the session map to look up which node to forward the request to, avoiding the need to involve the
distributor entirely. This means that you can just keep adding nodes to the Grid, and there are fewer bottlenecks
in the architecture to slow your requests down.&lt;/p>
&lt;p>Conceptually, there are these five moving pieces within the Grid. But there&amp;rsquo;s actually a sixth one, which is a
message bus. The five Grid components communicate internally through the message bus, but the actual components
that you need to think about when you&amp;rsquo;re thinking about the Grid are the Router, Session Queue, Distributor, and
Nodes.&lt;/p>
&lt;p>When you run Selenium Grid 4 in “standalone” mode, you actually get a “grid of one”. We wire up all these
components in a single process, but they’re all still there.&lt;/p>
&lt;p>You can also run it in the traditional Hub and Node approach that you&amp;rsquo;ve seen with Selenium Grid 2, where you
fire up a Hub and a Node and it registers. If you&amp;rsquo;ve used Selenium Grid recently, that&amp;rsquo;s probably the architecture
that you&amp;rsquo;re familiar with. In this case, most of the components (the router, session queue, and distributor) are
running in the Hub, and the Nodes run the sessions themselves.&lt;/p>
&lt;p>What’s new with Grid 4 is that you can go into a fully distributed mode if you want to. Typically, you would want
to use something like Kubernetes for this, and some of the key components are designed to store data using a
database or Redis for better reliability and scalability.&lt;/p>
&lt;p>Something to note is that when running a distributed Grid, it becomes really difficult to figure out what is
happening, particularly when something goes wrong. To alleviate that problem, we have adopted Open Telemetry to
bring observability into the Grid. What do we mean by observability? It simply means that we want to be able to
see everything that happens.&lt;/p>
&lt;p>Finally, we’d like to expose information about the running Grid in meaningful and useful ways. The original
Grid supported both JMX (a Java management API) and an HTML-based console. While nice, this didn’t make it easy
to query specific areas of the Grid that you might be interested in that weren’t surfaced by the UI (for example,
how many slots are available, or to find out which node a particular session is running on) To provide more
flexibility, we’ve chosen to provide a GraphQL endpoint for the Grid. To ensure that GraphQL endpoint is
sufficiently flexible, we’re building the new Grid console using it. That should allow you to also extract useful
metrics and information from the Grid for your monitoring needs.&lt;/p>
&lt;p>Those are some highlights of the new Selenium Grid. What are you the most excited about?&lt;/p>
&lt;p>&lt;em>This was originally posted at &lt;a href="https://saucelabs.com/blog/whats-coming-in-selenium-4-the-new-selenium-grid">https://saucelabs.com/blog/whats-coming-in-selenium-4-the-new-selenium-grid&lt;/a>&lt;/em>&lt;/p></description></item><item><title>Blog: Results of the first ever selenium survey</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/selenium-survey-results/</link><pubDate>Tue, 12 Jan 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/selenium-survey-results/</guid><description>
&lt;p>Below is a summary of the Selenium survey that was collected.&lt;/p>
&lt;h2 id="batteries-included">Batteries included&lt;/h2>
&lt;h3 id="browser-management">Browser Management&lt;/h3>
&lt;p>Unsurprisingly, people find having to manage browsers a task they wish they didn’t have to do and wish that Selenium did this. 59.5% of respondents want Selenium to manage the browsers for them. This, though the question didn’t ask this, is to include the browser drivers.&lt;/p>
&lt;h3 id="frameworks">Frameworks&lt;/h3>
&lt;p>The results show an interesting view into framework usage. 61% of users use a framework. When we look closer at some of the responses there could be a little language bias in there. Some responses in the “both” category are “depends on the language” or “depends on the project”. Frameworks, from a couple responses seem to be around JavaScript mostly.&lt;/p>
&lt;h2 id="how-tests-are-run">How tests are run&lt;/h2>
&lt;p>One of the questions that was the most surprising was that people dislike running their tests in headless. 57% of people don’t want headless. This is surprising since puppeteer and playwright are up and coming tools that default to headless.&lt;/p>
&lt;h3 id="browsers">Browsers&lt;/h3>
&lt;p>People tend to favour evergreen, or the latest version from auto updating browsers, with over 55% of people wanting that. When we look at the data closer then people tend to do evergreen and then a specific version for IE.&lt;/p>
&lt;p>People are also, overwhelmingly I should add, wanting to test on multiple browsers. 78% of people test with multiple browsers. This goes against the Chrome only support that we see on social media. The most used browsers for testing are (Percentage of respondents testing with browser):&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Google Chrome (98%)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Firefox (67%)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Microsoft Edge (33%)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Safari (29%)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>IE (13.5%)&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>One thing that is clear is that Testing against multiple browsers is hard. 51.6% say it’s hard and a further 27.3% being 3 out of 5. This is likely where some frameworks are becoming popular as it removes some of the need to understand the asynchronicity of browsers. This still has its problems in puppeteer and playwright as they add similar wait libraries to what Selenium has.&lt;/p>
&lt;h3 id="mobile-browsers">Mobile Browsers&lt;/h3>
&lt;p>One of the most surprising things to have come out of survey was the want to use mobile browsers more.&lt;/p>
&lt;p>Of the 410 respondents 367 want to test on mobile. Interestingly, this goes well past just Chrome for Android and Safari for iOS.&lt;/p>
&lt;p>Below is a list of browsers and percentage of users wanting to use it. Questions were designed for Android unless it said iOS. See note at the end of the section.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Firefox for Android: 38%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Chrome: 91%*&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Microsoft Edge: 14%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Samsung Internet: 16.6%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Safari on iOS: 69%&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>*Note that the questionaire only mentioned Chrome so it could be a conflation between platforms here. 1 Person used the other field to add Chrome for iOS.&lt;/p>
&lt;h3 id="language-support">Language support&lt;/h3>
&lt;p>Language support is what one would suspect with most users using Java or python.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>java: 67%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>python: 31%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>ruby: 6.1%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>.NET: 17.6%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>JavaScript: 21.4%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>PHP: 1.5%&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="improvements">Improvements&lt;/h2>
&lt;p>After reviewing the “What one thing would you improve about Selenium I was able to narrow most of the responses down to similar types.&lt;/p>
&lt;p>Below is a breakdown of the issues that people would like to see improved.&lt;/p>
&lt;figure>
&lt;img src="https://trunk--polite-jelly-cc0866.netlify.app/images/blog/2021/breakdown_of_answers.png"
alt="Breakdown of answers of areas needing improvement. Main 3 areas are flakiness, documentation, Browser Management, Shadow DOM"/>
&lt;/figure>
&lt;h2 id="happiness">Happiness&lt;/h2>
&lt;p>Of the 410 respondents, 219 had something nice to say about Selenium and were thankful for the product being around.&lt;/p>
&lt;p>Some of the main reasons are simplicity of APIs, good backwards compatibility, and it being open source&lt;/p></description></item><item><title>Blog: New Tricks in Selenium 4</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/what-is-coming-in-selenium-4-new-tricks/</link><pubDate>Wed, 16 Dec 2020 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/what-is-coming-in-selenium-4-new-tricks/</guid><description>
&lt;blockquote>
&lt;p>In the third post in his series, Simon Stewart continues talking about what&amp;rsquo;s coming in
Selenium 4 and reviews some of the tricks in the new release.&lt;/p>
&lt;/blockquote>
&lt;p>In my last posts, we talked about
&lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/what-is-coming-in-selenium-4-how-can-i-contribute">how to contribute to Selenium&lt;/a>, and
&lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/what-is-coming-in-selenium-4-why-the-major-version-bump">why we’re bumping the version number to 4&lt;/a>.
That’s enough preamble! Today, we’ll cover some details about the new tricks and capabilities
that Selenium 4 offers.&lt;/p>
&lt;h2 id="finding-elements-and-relative-locators">Finding Elements, and Relative Locators&lt;/h2>
&lt;p>You know, finding elements on a page can be really difficult. I&amp;rsquo;ve seen loads of people using
very complicated XPATH expressions, and trying to figure out complex CSS selectors and things
like that. There have been whole talks about the subject at SeleniumConf. Surely there must
be a better way to do this?&lt;/p>
&lt;p>Think about how we describe where an element is on the page. Think about how you’d do this
over the phone. You’d never talk about the raw DOM, “Ah, find the fifth DIV element nested
inside the SPAN with an ‘id’ of ‘foo’”. You’d just never say that! Instead, you’d say
something like, “just find that thing above that image, and to the right of that link,”
when talking about where things are located on the page.&lt;/p>
&lt;p>A long time ago, a project called &lt;a href="https://sahipro.com">Sahi&lt;/a> started to locate elements
like this. Sahi had &lt;a href="https://sahipro.com/docs/sahi-apis/accessor-api-basics.html#Use%20of%20Positional%20Relation%20APIs">Relation APIs&lt;/a>, which are a lovely way of finding elements,
and it was very, very fluent and pleasant to use. When I was starting WebDriver years ago,
I was talking with &lt;a href="https://twitter.com/narayanraman">Narayan&lt;/a> (creator of Sahi) and I
promised him that I was going to hold off implementing this flagship feature of Sahi. It
was something that was lovely, but it was also something Sahi was rightly proud of. However,
there are now other tools, such as Tyco, that are implementing this style of API, so it
seems like the time is right to do the same in Selenium. In Selenium 4 we call them
“relative locators.” You may sometimes see us refer to them as “friendly locators,” since the
initial implementation called them that, but “relative” better describes how they work. We
have a handful of them: near, above, below, left of, right of. They allow you to talk in human
language about where an element is on a page.&lt;/p>
&lt;p>Looking at the future, we are also planning to enable users to add new types of locators,
not only on the, on the client side, but also to the Selenium Server. For example, although
JS UI frameworks come and go (anyone else remember using jquery?), it’d be nice to be able
to add a custom locator for the current tools people like, such as React.&lt;/p>
&lt;h2 id="authenticating-to-web-sites">Authenticating to Web Sites&lt;/h2>
&lt;p>One feature that people have been asking for since we started the project has been the ability
to authenticate to a web site. Previously, you could do this by crafting the URL the browser
went to properly, but this leaks credentials to any man-in-the-middle and leaves them in server
logs, so browsers have slowly removed this piece of functionality. That’s unfortunate, since
it’s something that we know people frequently need to do in their tests. In Selenium 4, we
now offer a mechanism to register a username and password that can be used to authenticate against these sites.&lt;/p>
&lt;h2 id="intercepting-network-traffic">Intercepting Network Traffic&lt;/h2>
&lt;p>A common complaint of Selenium tests is that they’re slow and flaky. While the bindings to the
browser are excellent, and fully described by the W3C WebDriver spec, it is true that any end-to-end
test is likely to suffer more flakiness than a simple unit test—there are just more moving parts,
and more possibilities for things to go wrong.&lt;/p>
&lt;p>One way to resolve this issue is to stub out the backend of the application, intercepting network
traffic in the test and returning pre-canned responses. Tools such as &lt;a href="http://www.mbtest.org">mountebank&lt;/a>
make this easy for API testing. Wouldn’t it be nice if there was a similar tool for Selenium?&lt;/p>
&lt;p>With Selenium 4, we now provide a mechanism to do this, using the NetworkInterceptor (well, that’s
what we call it in the Java bindings). Pass it your WebDriver instance, and it’ll be called every time
the browser is about to make an HTTP request, allowing you to return almost anything you want&lt;/p>
&lt;h2 id="the-chrome-debugging-protocol">The Chrome Debugging Protocol&lt;/h2>
&lt;p>As I mentioned previously, one of the nice things about Selenium 4 is our work to ensure a stable
and modern user-facing API. What does this mean? To start, we need to acknowledge that after a long
time there’s now competition back in the browser automation space. Notably in the form of Puppeteer
and Cypress, and taking a step back, what do they offer? They build upon the
&lt;a href="https://chromedevtools.github.io/devtools-protocol/">Chrome DevTools Protocol (CDP)&lt;/a>&amp;gt;, which is a
protocol developed to enable a debugger inside Chromium-based browsers.&lt;/p>
&lt;p>Because of what it was designed to do, it is a chatty protocol, and not a user-facing API that
allows you to introspect into the browser. Worse, introduce a network hop between the test and the
browser, this chattiness leads to slower tests as the network latency increases. That is why tools
such as Puppeteer want you to run on the local machine. That’s great for the speed of an individual
test, but makes parallelisation harder, as you can&amp;rsquo;t use services such as Sauce Labs easily.&lt;/p>
&lt;p>To complicate matters, because the CDP is designed as a &lt;em>debugging&lt;/em> protocol, it can change with no
notice between versions. That’s why Puppeteer and Cypress are tied to specific versions of browsers,
and that causes a dilemma for you as a test author: how do you test on multiple versions of a browser?
Updating the test API to get a different browser can lead to you no longer making valid API calls.
Not doing so ties you to a potentially outdated version of a browser.&lt;/p>
&lt;p>Despite this, using the CDP opens up a host of possibilities, and that’s why we’ve added support
for it in Selenium 4. In fact, some of our new features are built on top of it (though we hide the details!)&lt;/p>
&lt;p>But we’ve also gone further that just adding basic support. Selenium 4 can support multiple versions
of the CDP at the same time, meaning you can test with both the current and beta versions of Chromium-based
browsers without needing to rewrite tests. We do this by providing an “idealised CDP”, which is
stable and covers the features we feel tests need. If that idealised view of the world isn’t enough
for you, we also expose the raw CDP APIs too, giving you flexibility to choose what’s best for your tests.&lt;/p>
&lt;p>We’re feeding this experience into the new W3C WebDriver Bidi specification, which is helping make that
a better fit for testers.&lt;/p>
&lt;p>I am leaving out of this post all the details related to another important trick in Selenium 4, the new
Selenium Grid, which I will cover in the next post. Stay tuned!&lt;/p>
&lt;p>&lt;em>This was originally posted at &lt;a href="https://saucelabs.com/blog/new-tricks-in-selenium-4">https://saucelabs.com/blog/new-tricks-in-selenium-4&lt;/a>&lt;/em>&lt;/p></description></item><item><title>Blog: What’s Coming in Selenium 4: Why The Major Version Bump?</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/what-is-coming-in-selenium-4-why-the-major-version-bump/</link><pubDate>Tue, 10 Nov 2020 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/what-is-coming-in-selenium-4-why-the-major-version-bump/</guid><description>
&lt;blockquote>
&lt;p>In the second post in this series, Simon Stewart continues talking about
what&amp;rsquo;s coming in Selenium 4 and why this release has a major version bump.&lt;/p>
&lt;/blockquote>
&lt;p>In my &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/what-is-coming-in-selenium-4-how-can-i-contribute/">last post&lt;/a>,
I shared a bit about how the Selenium project works overall. Now, let’s start talking about Selenium 4
and what’s coming. One thing I think I should clear up is &amp;ldquo;why the major version number bump?&amp;rdquo;&lt;/p>
&lt;p>Sometimes I joke that the major reason for the version number bump is that while the digits of Pi are
infinite, when we went from 3.14 to 3.141, people got a little bit upset. Moving to 3.141.5 and then
3.141.59 was as far as we wanted to push that particular idea :)&lt;/p>
&lt;p>More seriously, the first reason is that we have a revised Selenium IDE. Years ago, this used to be
Firefox only because it used the XPI extension mechanism (which was specific to Firefox). It’s now a
web component, and you can download it for Chrome, Firefox, and anything else that supports Web
Components. There is currently work to rewrite it as an Electron app, which will allow us to make
better use of the native OS the IDE is running on. That work was largely pushed forward by developers
working at Applitools. They started from a base of the original Selenium IDE that had been migrated
to use Web Components by a company called SideX. It’s been a fantastic example of the community
working together well.&lt;/p>
&lt;p>Secondly, we have fully adopted the W3C WebDriver protocol, and have dropped support for the original
home-grown wire protocol. The way that Selenium communicates with a web browser is via a wire protocol
that’s effectively just JSON over HTTP. Originally this grew organically as we figured things out,
and we tried to make browsers do what we needed them to. That original protocol is known as the JSON
wire protocol because it spoke JSON over the wire (and we’re not great at coming up with very original names).&lt;/p>
&lt;p>That original protocol was the base for the W3C WebDriver protocol, which smoothed some of the rough
edges, and brought some much needed consistency to the protocol. The two major areas the standardised
protocol improved on included session creation, where we removed considerable ambiguity, and by providing
a far richer API for specifying user actions.&lt;/p>
&lt;p>So what does this adoption of the W3C protocol mean for you? I&amp;rsquo;ll be honest: it probably doesn’t mean
much to you at all. If you&amp;rsquo;re using a modern browser (released over the past couple of years), you will
find that actually you already speak the W3C protocol with Selenium 3.&lt;/p>
&lt;p>So who does care about the protocol dialects? When we talk about companies like Sauce Labs who provide
Selenium as a service—they care about it. The ecosystem is ready for this next step, because the
technical folks at these companies have ensured that they understand and comply with the W3C protocol,
and folks from the Selenium project have been there offering help and advice as needed.&lt;/p>
&lt;p>One of the other nice things about Selenium 4 is that we&amp;rsquo;ve done our best to ensure a stable user-facing
API. That means when you upgrade your project from Selenium 3 to Selenium 4, it should be a drop-in
upgrade. You just change the version number, recompile and you should be done.&lt;/p>
&lt;p>There are a few caveats that you should be aware of, however! The major one is that if in the last version
of Selenium 3 a method was deprecated, it’s now probably gone. We’ve taken the opportunity of a major
version bump to delete them and clean up the behind-the-scenes internals people don’t normally get to see.
If you’re a software developer, you may recognise this as us paying off some of our technical debt :)&lt;/p>
&lt;p>Stay tuned for the next post, where I’ll go over some new tricks in Selenium 4.&lt;/p>
&lt;p>&lt;em>This was originally posted at &lt;a href="https://saucelabs.com/blog/whats-coming-in-selenium-4-why-the-major-version-bump">https://saucelabs.com/blog/whats-coming-in-selenium-4-why-the-major-version-bump&lt;/a>&lt;/em>&lt;/p></description></item><item><title>Blog: What’s Coming in Selenium 4: How Can I Contribute?</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/what-is-coming-in-selenium-4-how-can-i-contribute/</link><pubDate>Mon, 02 Nov 2020 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/what-is-coming-in-selenium-4-how-can-i-contribute/</guid><description>
&lt;blockquote>
&lt;p>In this new blog series all about the upcoming release of Selenium 4, Simon Stewart will
cover how the Selenium project works, who is involved, how you can get involved, and a
sneak peek at what’s new in Selenium 4.&lt;/p>
&lt;/blockquote>
&lt;p>As the lead of the Selenium project, I wanted to kick off a new blog series leading up to
the release of Selenium 4. During this series, I’ll talk all about how the Selenium project
works, who is involved, how you—yes, you!—can get involved, and we’ll get a sneak peek at
what’s new in Selenium 4. I&amp;rsquo;ve been speaking about this off and on for a while, but now
the 4.0 release is looming I wanted to start sharing in more depth.&lt;/p>
&lt;p>In this first post, we’ll start off with a brief discussion about how the Selenium project
itself runs and who does what, because that’s a really helpful piece to understand how and
why things happen the way they do on the project. In future posts, we’ll look at the new IDE,
and then we’ll talk about Selenium 4 in more depth, including the fact that it should be a
drop-in replacement for you. I’ll also review some new features that we’ve added to Selenium
4, and talk a bit about the modernized Selenium Grid. So let’s get started!&lt;/p>
&lt;h2 id="about-the-selenium-project">About the Selenium Project&lt;/h2>
&lt;p>Selenium is an Open Source project. It&amp;rsquo;s run under the aegis of the Software Freedom
Conservancy (SFC). The SFC is a group dedicated to pushing forward Free and Open Source
software. Besides Selenium, they have a handful of projects you may have heard of, including
Samba, Mercurial and Git. The SFC allows us to focus on writing code and fixing bugs by
handling all the legal and financial stuff we’re not good at. They’re the ones that help
us negotiate contracts for when we want to run SeleniumConf, for example.&lt;/p>
&lt;p>Acting as a bridge between the project and the SFC is the Project Leadership Committee
(PLC). Currently, it’s made up of Jim Evans, Alexei Barantsev, Marcus Merrell, Manoj Kumar,
and myself. What do we do? Effectively, the PLC is about providing a smaller group of people
for the SFC to talk to when decisions need to be made about funding a conference, or how
best to respond to sponsorship agreements. Because we like to do as much work in the open
as possible, you can find us on the &lt;code>#selenium-plc&lt;/code> Slack channel, and almost every
conversation and topic is discussed here.&lt;/p>
&lt;p>One of the key qualifications for being on the PLC is a demonstrated commitment to helping
the Selenium project improve and succeed, and we recognise that the project is more than just
“code.” It’s a community, and the make up of the PLC reflects that.&lt;/p>
&lt;p>The Technical Leadership Committee (TLC) includes the people who set the technical direction
for the project. If you come over to the Selenium Slack, you can find the &lt;code>#selenium-tlc&lt;/code> channel,
which is where a lot of the technical conversations happen for the project. The TLC includes Jim
Evans, Alexei Barantsev, David Burns, Diego Molina, Titus Fortner, and me.&lt;/p>
&lt;p>How do you get on the TLC? Although the project governance document goes into more detail,
it can be summed up as simply as someone who’s demonstrated technical leadership on the project,
over an extended period of time. Just as with the PLC, being on the TLC doesn’t give someone more
authority, but they’re the ones who can merge PRs, and who can (if need be) commit directly to the tree.&lt;/p>
&lt;p>Again, the TLC tries to do as much work as possible in the open. If you’re ever interested in watching
the design discussions, or asking why a bit of the Selenium code base is structured the way it is, then
come and join us in the &lt;code>#selenium-tlc&lt;/code> Slack channel. There’s normally someone from the project there
who’ll be able to answer your questions!&lt;/p>
&lt;p>I wanted to share how the project works for one simple reason: to highlight one of the really important
things with Open Source, which is that anyone can contribute! You don&amp;rsquo;t need to be throwing code around
in order to be contributing, and &lt;a href="https://www.youtube.com/watch?v=PZ-BfM97PZk">you don’t need to be special&lt;/a>
in order to contribute your time and effort.&lt;/p>
&lt;p>So obviously there&amp;rsquo;s the people running the projects and writing code, but we couldn&amp;rsquo;t do that all on our own.
Every release includes contributions from a variety of people, not just the core development team. Also, we&amp;rsquo;re
always happy to accept patches. If you&amp;rsquo;re not quite sure where to start, I recommend you head to our
&lt;a href="https://github.com/seleniumhq/selenium/">GitHub page&lt;/a> and take a look at the project tab. That’s where you
can see the things that need to be done and what we&amp;rsquo;re working on.&lt;/p>
&lt;p>The other way to get involved is the way that everyone used to get involved with Open Source, which is by
what&amp;rsquo;s known as “scratching your own itch”. It&amp;rsquo;s if there&amp;rsquo;s something about the project, something about the
product you think could be a little bit better, download the source, edit it, and then send us a PR.&lt;/p>
&lt;p>We encourage you to get involved and contribute! On the Selenium website, there is a
&lt;a href="https://www.selenium.dev/governance/">page&lt;/a> that outlines in detail the steps to join the Selenium team.
Join the Selenium Slack channel to interact with us and ask questions. If you want to discuss something,
or if you don&amp;rsquo;t understand why the code is written the way it is, feel free to come on to that Slack channel
and talk to us. Also, if you&amp;rsquo;d like to see how the decision making is made, then please do feel free to come
on to the &lt;code>#selenium-tlc&lt;/code> or the &lt;code>#selenium-plc&lt;/code> channels to see those groups. Because we&amp;rsquo;re Open Source, we
try and do everything in the open.&lt;/p>
&lt;p>If you’d like to put faces to people’s Slack or IRC handles, then please note that there’s a regular team
meeting every other Thursday on Google Meet at 4:30pm (UK time!) We tend to just chat and discuss everything
from the project to the weather, but that’s a great way to get to know people a little better! :)&lt;/p>
&lt;p>Finally, if you’re having trouble getting to grips with the Selenium code base, then please do come and ask us
for help. We’ve done our best to make the on-ramp as easy to take as possible, but the project can seem complicated
and daunting when you’re getting started. We’re here to help!&lt;/p>
&lt;p>I hope you enjoyed this intro to the Selenium project. Next week, we’ll talk about why the major version bump to
Selenium 4. Stay tuned!&lt;/p>
&lt;p>&lt;em>This was originally posted at &lt;a href="https://saucelabs.com/blog/whats-coming-in-selenium-4-how-can-i-contribute">https://saucelabs.com/blog/whats-coming-in-selenium-4-how-can-i-contribute&lt;/a>&lt;/em>&lt;/p></description></item><item><title>Blog: Browser Testing and Tools WG Meeting @ TPAC 2020</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/webdriver-tpac-meeting-2020/</link><pubDate>Thu, 29 Oct 2020 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/webdriver-tpac-meeting-2020/</guid><description>
&lt;p>It&amp;rsquo;s that time of the year where working groups from the W3C meet up to discuss the various standards that
are being worked on.&lt;/p>
&lt;p>Within the Browser Testing and Tools Working Group, there are 2 different standards.&lt;/p>
&lt;p>We have:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://w3c.github.io/webdriver/">WebDriver&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://w3c.github.io/webdriver-bidi">WebDriver-Bidi&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The first is what is commonly supported by the Selenium Project and has support from Apple, Mozilla, Microsoft, and Google in their browsers. It is also supported by various Selenium in the cloud providers like Sauce Labs and BrowserStack.&lt;/p>
&lt;p>As the world has moved on we have felt the need to add new APIs and move Selenium to be more event-driven. This is where we are learning, and collaborating, with projects like Puppeteer to make sure that we can improve the Browser Automation space. This is where the &lt;a href="https://w3c.github.io/webdriver-bidi">WebDriver-Bidi&lt;/a> Specification comes in. It has broad support from the browser vendors so you can use official browsers and not be limited by the JavaScript sandbox. Some of the newer frameworks can&amp;rsquo;t guarantee that.&lt;/p>
&lt;p>If you&amp;rsquo;re curious about we discussed this week, feel free to read it up on the &lt;a href="https://www.w3.org/wiki/WebDriver/2020-TPAC">W3 Wiki&lt;/a>.&lt;/p>
&lt;p>This post was originally shared on David Burns&amp;rsquo; &lt;a href="https://www.theautomatedtester.co.uk/blog/2020/webdriver-tpac-meeting-2020/">Blog&lt;/a>&lt;/p></description></item><item><title>Blog: Selenium 4.0 Alpha 6 is out!</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/selenium-4-alpha-6-is-out/</link><pubDate>Mon, 01 Jun 2020 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/selenium-4-alpha-6-is-out/</guid><description>
&lt;p>We are very pleased to announce the release of &lt;a href="http://www.selenium.dev/downloads/">Selenium 4.0 Alpha 6&lt;/a>.&lt;/p>
&lt;p>All the information can be seen in different tweets from the project contributors, here they are all in one place:&lt;/p>
&lt;p>&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">Happy Friday! I&amp;#39;ve just pushed Selenium 4.0a6 for Java. There&amp;#39;s a lot of nice changes:&lt;br>&lt;br>* Full remoting of the CDP protocol across the Grid&lt;br>* The skeleton of our GraphQL support&lt;br>* Better configuration options, especially for Nodes, via TOML&lt;br>* A bajillion improvements &amp;amp; fixes&lt;br>&lt;br>1/5&lt;/p>&amp;mdash; Simon Mavi Stewart (@shs96c) &lt;a href="https://twitter.com/shs96c/status/1266307374941437952?ref_src=twsrc%5Etfw">May 29, 2020&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">As ever, this release is the product of hard work and contributions not only from the core team (special thanks to &lt;a href="https://twitter.com/barancev?ref_src=twsrc%5Etfw">@barancev&lt;/a> and &lt;a href="https://twitter.com/diemol?ref_src=twsrc%5Etfw">@diemol&lt;/a>. You&amp;#39;ve done amazing work!) but also from a host of other people. In that spirit, I&amp;#39;d like to thank… 2/5&lt;/p>&amp;mdash; Simon Mavi Stewart (@shs96c) &lt;a href="https://twitter.com/shs96c/status/1266307376279359488?ref_src=twsrc%5Etfw">May 29, 2020&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">In no particular order:&lt;br>&lt;br>* Amit Bhoraniya&lt;br>* @bongosway&lt;br>* Gerry Gao&lt;br>* Sridhar Upputuri&lt;br>* John Chen&lt;br>* @alb_i986&lt;br>* Rahul Shah&lt;br>* &lt;a href="https://twitter.com/ulfjack?ref_src=twsrc%5Etfw">@ulfjack&lt;/a> &lt;br>&lt;br>I&amp;#39;ve linked to the twitter handle where I know it. Give &amp;#39;em a high five! Selenium wouldn&amp;#39;t be possible without the help of the community! 3/5&lt;/p>&amp;mdash; Simon Mavi Stewart (@shs96c) &lt;a href="https://twitter.com/shs96c/status/1266307377420275713?ref_src=twsrc%5Etfw">May 29, 2020&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">I&amp;#39;m hoping that the next alpha will be the last alpha. The &amp;quot;big ticket&amp;quot; items remaining are:&lt;br>&lt;br>* Provide nice APIs to take advantage of the CDP&lt;br>* Flesh out the GraphQL support&lt;br>* A nice UI to take advantage of the GraphQL endpoint&lt;br>* Robustness work in the Grid&lt;br>&lt;br>4/5&lt;/p>&amp;mdash; Simon Mavi Stewart (@shs96c) &lt;a href="https://twitter.com/shs96c/status/1266307378485563392?ref_src=twsrc%5Etfw">May 29, 2020&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">You can come and join in the fun by either heading over to the GitHub project and picking a task (&lt;a href="https://t.co/2ifj6CkeEV">https://t.co/2ifj6CkeEV&lt;/a>) or (and!) coming to have a chat on Slack &lt;a href="https://t.co/4aEDqyI6gq">https://t.co/4aEDqyI6gq&lt;/a> 5/5&lt;/p>&amp;mdash; Simon Mavi Stewart (@shs96c) &lt;a href="https://twitter.com/shs96c/status/1266307379513171968?ref_src=twsrc%5Etfw">May 29, 2020&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">I have just tagged &lt;a href="https://twitter.com/hashtag/Selenium?src=hash&amp;amp;ref_src=twsrc%5Etfw">#Selenium&lt;/a> 4a6 on GitHub. It&amp;#39;s got a lot of nice cleanups as we edge closer to a proper &lt;a href="https://twitter.com/hashtag/Selenium?src=hash&amp;amp;ref_src=twsrc%5Etfw">#Selenium&lt;/a> 4 release!&lt;/p>&amp;mdash; David @automatedtester@mastodon.social (@AutomatedTester) &lt;a href="https://twitter.com/AutomatedTester/status/1266025050706149379?ref_src=twsrc%5Etfw">May 28, 2020&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">selenium-webdriver 4.0.0.alpha6 has just been released. The biggest change is an experimental support for Chrome DevTools protocol! Read more in changelog &lt;a href="https://t.co/1l2XYkaEfB">https://t.co/1l2XYkaEfB&lt;/a>.&lt;a href="https://twitter.com/hashtag/selenium?src=hash&amp;amp;ref_src=twsrc%5Etfw">#selenium&lt;/a> &lt;a href="https://twitter.com/hashtag/ruby?src=hash&amp;amp;ref_src=twsrc%5Etfw">#ruby&lt;/a> &lt;a href="https://twitter.com/hashtag/devtools?src=hash&amp;amp;ref_src=twsrc%5Etfw">#devtools&lt;/a>&lt;/p>&amp;mdash; Alex Rodionov (@p0deje) &lt;a href="https://twitter.com/p0deje/status/1266144106885111814?ref_src=twsrc%5Etfw">May 28, 2020&lt;/a>&lt;/blockquote>
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;/p>
&lt;p>Happy hacking!&lt;/p></description></item><item><title>Blog: Selenium IDE Is Dead, Long Live Selenium IDE!</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2018/long-live-selenium-ide/</link><pubDate>Mon, 06 Aug 2018 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2018/long-live-selenium-ide/</guid><description>
&lt;p>In August of 2017 Simon shared the bleak, hard news that as of Firefox 55 Selenium IDE would no longer work.
Selenium IDE (or as we’ll refer to it from here on out – the Legacy IDE) was, and is, dead.&lt;/p>
&lt;p>Since then quite a lot has happened with the IDE. We have a new version of it which we are referring to as… Selenium IDE!&lt;/p>
&lt;p>&lt;strong>It is currently in “alpha” and available for use in both
&lt;a href="https://chrome.google.com/webstore/detail/selenium-ide/mooikfkahbdckldjjndioackbalphokd">Chrome&lt;/a> and
&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/selenium-ide/">Firefox&lt;/a>.&lt;/strong>&lt;/p>
&lt;p>In his post Simon also mentioned “the fine people at &lt;a href="https://applitools.com">Applitools&lt;/a>“. This includes Tomer Steinfeld,
Dave Haeffner, and Doron Zavalevsky. Together, along with contributions from the rest of the Selenium community and
the SideeX project, we have been able to get the new Selenium IDE out into the wild. We are also working to close the gap
on feature parity with its predecessor along with adding some much needed enhancements to the tool (more on that in future posts).&lt;/p>
&lt;p>We’d love for you to give the new IDE a try and let us know what you think. Visit either the
&lt;a href="https://chrome.google.com/webstore/detail/selenium-ide/mooikfkahbdckldjjndioackbalphokd">Chrome Web Store&lt;/a> or
&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/selenium-ide/">Firefox Add-ons&lt;/a> to install it. For info on how to
use the tool, you can check out the getting started documentation on Selenium HQ.&lt;/p>
&lt;p>If you have any questions you can find us on the &lt;a href="https://selenium.dev/support/">Selenium Slack/IRC chat channel&lt;/a>.
Think you found a bug? &lt;a href="https://github.com/SeleniumHQ/selenium-ide/issues">File an issue&lt;/a>. Want to contribute?
Take a look at the project on &lt;a href="https://github.com/SeleniumHQ/selenium-ide">GitHub&lt;/a>.&lt;/p>
&lt;p>Happy Testing!&lt;/p></description></item><item><title>Blog: Firefox 55 and Selenium IDE</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2017/firefox-55-and-selenium-ide/</link><pubDate>Wed, 09 Aug 2017 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2017/firefox-55-and-selenium-ide/</guid><description>
&lt;p>The bad news: &lt;strong>from Firefox 55 onwards, Selenium IDE will no longer work&lt;/strong>.&lt;/p>
&lt;p>The reasons for this are complex, but boil down to two main causes:&lt;/p>
&lt;ol>
&lt;li>Browsers are complicated pieces of software that are constantly evolving. Mozilla has been working hard to make Firefox &lt;a href="https://blog.mozilla.org/blog/2017/06/13/faster-better-firefox/">faster and more stable&lt;/a>, while still retaining the flexibility and ease of extension that we’ve come to know and love. As part of that process, Firefox is switching extensions from the original “&lt;a href="https://blog.mozilla.org/addons/2016/11/23/add-ons-in-2017/">XPI&lt;/a>” format, to a newer, more widely adopted “&lt;a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions">Web Extension&lt;/a>” mechanism.&lt;/li>
&lt;li>The Selenium project lacks someone with the time and energy to move the IDE forwards to take advantage of the new technologies.&lt;/li>
&lt;/ol>
&lt;p>&lt;a href="http://www.seleniumhq.org/">Selenium&lt;/a> is one of the most widely used pieces of testing software there is. Despite this, the team of people regularly contributing is small: since the start of the year, there are only 11 people who have made more than 10 commits, with two people accounting for more than half of those. Since 2016, only one person has been maintaining the IDE.&lt;/p>
&lt;p>Selenium is an Open Source project. None of the core contributors — not the IDE maintainer, not the language binding owners — are paid to work on work on it. They do it because they love working on the code, and they typically do it in their “copious free time”. The IDE maintainer has had almost none of that to spare. We should all be thanking that committer for his time and effort. Thank you, Samit!&lt;/p>
&lt;p>So what can we do to move forward? The first thing is that there are now a wealth of tools that are stepping up to fill the gap. You should go and have a look at them. The second thing is that there is an effort to rebuild IDE using modern APIs, to be usable across more than just Firefox. The fine people at &lt;a href="https://applitools.com/">Applitools&lt;/a> are helping with this effort.&lt;/p>
&lt;p>The third thing? That’s you. &lt;strong>You could help us&lt;/strong>.&lt;/p>
&lt;p>If you believe that a friendly UI for quickly recording and playing back tests is a useful Open Source tool, then please come and join us! The main technical discussions are happening on the #selenium IRC channel. If you’d prefer &lt;a href="https://seleniumhq.herokuapp.com/">Slack&lt;/a>, you can join us on that too. Or there’s the ever useful &lt;a href="https://groups.google.com/forum/#!forum/selenium-developers">selenium-developers&lt;/a> mailing list. Come onboard. We’d love your help, and IDE is a wonderful thing to contribute to!&lt;/p></description></item><item><title>Blog: Hacking with IntelliJ</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2017/hacking-with-intellij/</link><pubDate>Wed, 08 Feb 2017 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2017/hacking-with-intellij/</guid><description>
&lt;p>&lt;a href="https://www.jetbrains.com/">Jetbrains&lt;/a> have a &lt;a href="https://www.jetbrains.com/buy/opensource/">programme for Open Source projects&lt;/a> which allows them to receive &lt;a href="https://www.jetbrains.com/idea/">IntelliJ IDEA&lt;/a> licenses. As part of that programme, which the Selenium project has participated in for many years, they’ve asked us to provide a fair and balanced review of IntelliJ. I’ll attempt to do that, and I’ll try and state my biases up-front so you’re aware of them.&lt;/p>
&lt;p>I’ve been using Jetbrain’s IntelliJ to hack on the Selenium code since I started working on it slightly over ten years ago. It’s still my favourite IDE for my Java work, and it’s plenty of fun to use. For some time, I’ve been using the (free) Community Edition, which is ample for many coding needs.&lt;/p>
&lt;p>Most of my work is in Java, and that’s where I know IDEA best. I dabble in Ruby and Python, and I’ve written a reasonably large amount of Javascript, all in IDEA.&lt;/p>
&lt;p>The Pros:&lt;/p>
&lt;p>In common with other good IDEs, IDEA has the ability to work seamlessly with many different languages. If you’re a polyglot programmer, being able to stay in the same tool for much of your work makes life a lot easier. On the Selenium project, we use Java, C#, Ruby, Python, and Javascript extensively. I don’t do any C#, and I mainly focus on Java, but the support for JS, Ruby, and Python is lovely and seems to work well. The built in type detection and code navigation features are impressive (particularly for untyped languages such as JS)&lt;/p>
&lt;p>Of course, the feature that made IDEA so awesome in the first place is the range of refactoring options it offers. These are great, and always have been. One nice feature I’ve noticed as we move to a Java 8 future (finally!) is that it offers suggestions to help migrate to new features where they make sense (and, I’ll be honest, sometimes when they don’t). It’s made making use of lambdas a lot easier.&lt;/p>
&lt;p>For a while, IDEA was becoming slower and more bloated, but I’m pleased to see that, partly thanks to the work of developers from &lt;a href="http://facebook.com/">Facebook&lt;/a>, the latest releases feel snappier and handle larger projects more efficiently. One thing I appreciate is how open Jetbrains were to receiving patches to their core product: it displays a level of respect for external contributors that I feel is important (of course, I would think that: I work on OSS for fun!)&lt;/p>
&lt;p>There’s a nice wide range of plugins available for IDEA. I’ve hooked up the Buck plugin and made use of it. Without an extensions API, this plugin wouldn’t have been possible, but having them there is incredibly useful and makes the IDE even more capable.&lt;/p>
&lt;p>Finally for the plus points of the IDE, I love that the IDE tracks new versions of Java relatively closely — it’s fun to see what new language features we’ll be able to use in the future!&lt;/p>
&lt;p>The Cons:&lt;/p>
&lt;p>Although it’s a fine product, there are some niggles to be had.&lt;/p>
&lt;p>Most annoyingly, the built in code analysis doesn’t always warn that some Java classes won’t compile. The most recent example was where IDEA didn’t flag that some lambdas couldn’t be used since the choice of method to use was ambiguous. This may be because the Java language continues its slothful way forward, and the compiler improves with each release — certainly these same files compiled just fine with older Java releases.&lt;/p>
&lt;p>When an error does happen, I’ve yet to find the magic setting to allow IDEA to keep going as far as possible. One of the features I like about Eclipse is that it’ll compile as much as it can, even if there are invalid source files. When doing TDD, this allows you to move just a little bit faster as unit tests can run and pass so long as they don’t touch faulty code. I dearly wish this same capability was present in IDEA!&lt;/p>
&lt;p>On the Selenium project, we use &lt;a href="http://buckbuild.com/">Buck&lt;/a> for our builds. The Buck plugin doesn’t (yet!) allow me to build and run tests within the IDE, yet Buck performs some steps that can’t be repeated by the IDE that are required for a successful build. IDEA offers the ability to run an &lt;a href="http://ant.apache.org/">Ant&lt;/a> step before a build is run, and it would be extremely useful if this was generalised to “any shell command”. Most of the time, it’s fine, but it’s irksome to forget to run things!&lt;/p>
&lt;p>On the whole, I love IntelliJ an awful lot. It’s a fast and capable IDE, and the company behind it supports OSS. What’s not to love?&lt;/p></description></item><item><title>Blog: Selenium 3.0: Out Now!</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2016/selenium-3-0-out-now/</link><pubDate>Thu, 13 Oct 2016 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2016/selenium-3-0-out-now/</guid><description>
&lt;p>We are very pleased to announce the release of &lt;a href="http://www.seleniumhq.org/download/">Selenium 3.0&lt;/a>. If you’ve been waiting for a stable release since 2.53.1, now’s your chance to update. And if you do, here is what you’ll find:&lt;/p>
&lt;p>As &lt;a href="https://seleniumhq.wordpress.com/2016/10/04/selenium-3-is-coming/">we’ve said before&lt;/a>, for users of the WebDriver APIs this is a drop-in replacement. You’ll find that modern browsers, such as &lt;a href="https://chromedriver.chromium.org/downloads">Chrome&lt;/a> and &lt;a href="https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/">Edge&lt;/a> will continue to work just as before, and we’ve taken the opportunity to fix some bugs and improve stability. Selenium Grid users may require updates to their configuration as the json config file format has been updated, as have some of command line parameter options, but the upgrade should also be smooth.&lt;/p>
&lt;p>The major change in Selenium 3.0 is we’re removing the original Selenium Core implementation and replacing it with one backed by WebDriver. This will affect all users of the &lt;a href="http://seleniumhq.github.io/selenium/docs/api/java/com/thoughtworks/selenium/Selenium.html">Selenium RC&lt;/a> APIs. For more information, please see the &lt;a href="https://seleniumhq.wordpress.com/2016/10/04/selenium-3-is-coming/">previous post&lt;/a>.&lt;/p>
&lt;p>A lot has changed in the 5 years between versions 2 and 3. When we &lt;a href="https://seleniumhq.wordpress.com/2011/07/08/selenium-2-0/">shipped Selenium 2&lt;/a>, the Selenium project was responsible for providing the driver for each browser. Now, we are happy to say that all the major browser vendors ship their own implementations (&lt;a href="https://webkit.org/blog/6900/webdriver-support-in-safari-10/">Apple&lt;/a>, &lt;a href="https://chromedriver.chromium.org/">Google&lt;/a>, &lt;a href="https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/">Microsoft&lt;/a>, and &lt;a href="https://github.com/mozilla/geckodriver/releases">Mozilla&lt;/a>). Because the browser vendors know their browsers better than anyone, their WebDriver implementations can be tightly coupled to the browser, leading to a better testing experience for you.&lt;/p>
&lt;p>The other notable change has been that there is now a &lt;a href="https://www.w3.org/TR/webdriver/">W3C specification&lt;/a> for browser automation, based on the Open Source WebDriver. This has yet to reach “recommendation” status, but the people working on it (including members of the Selenium project!) are now focusing on finishing the text and writing the implementations.&lt;/p>
&lt;p>Mozilla has been a front-runner in implementing the W3C WebDriver protocol. On the plus side, this has exposed problems with the spec as it has evolved, but it also means that Firefox support is hard to track as their engineering efforts have been forward looking, rather than on supporting the current wire protocol used by Selenium WebDriver. For now, the best advice we can offer is for you to try the latest release of &lt;a href="https://github.com/mozilla/geckodriver/releases">geckodriver&lt;/a> and Selenium together.&lt;/p>
&lt;p>These are exciting times for browser automation! Selenium 3.0 is a major release and we’re looking forward to improving things further, as well as tracking the ongoing work of the W3C spec. Our goal is to keep the changes your tests need to deal with to an absolute minimum, to continue preserving the hard work that’s gone into writing your existing tests.&lt;/p>
&lt;p>As a personal note, I’d like to say thank you to each of the many people that have worked so hard to make Selenium 3 possible. That’s not just the developers and contributors to the Open Source project (past and present), but also the engineers from Google, Microsoft, Mozilla, and Apple, and everyone involved with the W3C spec. I’d also like to say thank you to everyone who’s taken the time to report bugs, our users and our community. The project is great fun to work on and you’re the reason for that. A final thank you is due to the Software Freedom Conservancy, who have provided invaluable help with the logistics of running a large OSS project.&lt;/p>
&lt;p>Happy hacking, everyone! May your tests run fast and true!&lt;/p></description></item><item><title>Blog: Selenium 3 is Coming</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2016/selenium-3-is-coming/</link><pubDate>Tue, 04 Oct 2016 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2016/selenium-3-is-coming/</guid><description>
&lt;p>&lt;a href="http://www.seleniumhq.org/download/">Selenium 3&lt;/a> is coming! As I write this, we think that “beta 4” will be the last beta before the official 3.0 release. I’m here to tell you about what’s changed, and what impact this will have on your testing.&lt;/p>
&lt;h3 id="tldr">TL;DR:&lt;/h3>
&lt;ul>
&lt;li>WebDriver users will just find bug fixes and a drop-in replacement for 2.x.&lt;/li>
&lt;li>Selenium Grid users will also find bug fixes and a simple update.&lt;/li>
&lt;li>The WebDriver APIs are now the only APIs actively supported by the Selenium project.&lt;/li>
&lt;li>The Selenium RC APIs have been moved to a “legacy” package.&lt;/li>
&lt;li>The original code powering Selenium RC has been replaced with something backed by WebDriver, which is also contained in the “legacy” package.&lt;/li>
&lt;li>By a quirk of timing, Mozilla have made changes to Firefox that mean that from Firefox 48 you must use their geckodriver to use that browser, regardless of whether you’re using Selenium 2 or 3.&lt;/li>
&lt;/ul>
&lt;h3 id="in-more-depth">In more depth:&lt;/h3>
&lt;p>When we &lt;a href="https://seleniumhq.wordpress.com/2011/07/08/selenium-2-0/">released Selenium 2.0&lt;/a> in 2011, we introduced the new WebDriver APIs, and encouraged everyone to start moving to them. If you’re using the WebDriver APIs, then Selenium 3.0 is a simple drop-in upgrade. We’ve not changed any of the public WebDriver APIs, and the code is essentially the same as the last 2.x release. If you’re using Selenium Grid, the same applies: in most cases, you can just drop in the new JAR (or update your maven dependency to 3.0.0), and you’re done.&lt;/p>
&lt;p>If the update to Selenium 3 is such a non-event, why did we call this Selenium 3.0? To answer this question, I first need to provide some history, and tell you a little about how Selenium works under the hood. The very first version of Selenium was “just” a very complicated Javascript framework, running in the browser and interpreting the table-based tests you may be familiar with if you use Selenium IDE. We call this “Selenium Core”. This Javascript framework formed the basis of the original implementation of Selenium RC (the oldest set of Selenium APIs, where all the method and functions were on the “&lt;a href="http://seleniumhq.github.io/selenium/docs/api/java/com/thoughtworks/selenium/Selenium.html">Selenium&lt;/a>” interface, and which have been deprecated for some time now). Over time, the needs of modern web testing have grown ever more complicated and sophisticated, and Selenium Core is now less capable of meeting these needs than it was before.&lt;/p>
&lt;p>With Selenium 3.0, we are deleting the original Selenium Core implementation. If you use the old RC interfaces, we provide an alternative implementation that’s backed by WebDriver. This is the same “webdriver-backed selenium” that has been available as part of Selenium 2 since its release. Because the underlying technology has changed from Selenium Core to WebDriver, you may find some places where your existing tests using RC run into issues. Our experience with migrating suites is that it’s normally a systemic issue that can be fixed with a minimal engineering effort (that is, the problem is normally isolated to a few places, and these can be rewritten to avoid problems)&lt;/p>
&lt;p>We’re also removing the original Selenium RC APIs from the main downloads. If you’re a Java user, and need to use them to support existing tests, then you’ll need a dependency to “org.seleniumhq.selenium:selenium-leg-rc:3.0.0” (or later!). It’s strongly recommended that you do not do this unless you absolutely need to.&lt;br>
If you’re someone who runs tests exported from IDE in the table format, there is now a new test runner that the project has made available for you to use that can be &lt;a href="http://www.seleniumhq.org/download/">downloaded&lt;/a> from the project’s website. It takes the same arguments as the old runner, and we’ve done our best to ensure the output of tests remains the same too.&lt;/p>
&lt;p>At the same time as the Selenium project is shipping Selenium 3.0, Mozilla are changing the internals of Firefox in a way that makes it more stable and secure, but which also makes the community provided Firefox Driver no longer work. As such, if you use Firefox for your testing, you’ll need to use the &lt;a href="https://github.com/mozilla/geckodriver/releases">geckodriver&lt;/a>, which is an executable similar to the &lt;a href="https://chromedriver.chromium.org/">chromedriver&lt;/a> and the &lt;a href="https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/">Microsoft WebDriver&lt;/a> for Edge. You’ll need to start using geckodriver even if you’re using Selenium 2 — the change is in the browser, not Selenium. Please be aware that geckodriver is alpha software, based on the evolving W3C WebDriver standard: everyone’s working flat out to give you the best testing experience they can, but there are undoubtedly some bumps in the road when it comes to testing with Firefox.&lt;/p>
&lt;p>This release marks the culmination of a lot of hard work by the Selenium committers and community. I’d like to thank everyone who has been part of this process, and the Selenium users around the world who have done so much to make the project as successful as it is.&lt;/p></description></item><item><title>Blog: Announcing Selenium 3.0-beta1</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2016/announcing-selenium-3-0-beta1/</link><pubDate>Fri, 29 Jul 2016 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2016/announcing-selenium-3-0-beta1/</guid><description>
&lt;p>At SeleniumConf in 2013, we announced that a new major version of Selenium would be released “by Christmas”. Fortunately, we never said which Christmas, as it has taken us a while to make all the changes we wanted to make! We’re excited to announce the release of the first beta — Selenium 3.0.0-beta1.&lt;/p>
&lt;p>We’d love you to try it out on your projects, and provide us with feedback on where the rough edges are before we ship the 3.0 itself! Please remember that this is a beta release, so your feedback is incredibly helpful and valuable in order to help us smooth any rough edges.&lt;/p>
&lt;p>For the last six years we’ve been advising users to switch to the newer WebDriver APIs and to stop using the original RC APIs. With Selenium 3.0, the original implementation of RC has been removed, replaced by one that sits on top of WebDriver. For many users, this change will go completely unnoticed, as they’re no longer using the RC APIs. For those of you who still are, we’ve done our best to make the change as smooth as possible, but &lt;a href="https://github.com/seleniumhq/selenium/issues">we welcome high quality bug reports&lt;/a> to help us fix any problems that occur. Maven users will need to add a dependency on the new “&lt;a href="http://docs.seleniumhq.org/download/maven.jsp">leg-rc&lt;/a>” package to access the old RC APIs.&lt;/p>
&lt;p>There are some other changes that you might need to be aware of:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>You’ll need to be running Java 8&lt;/strong> to use the Java pieces of Selenium. This is the oldest version of Java officially supported by Oracle, so hopefully you’re using it already!&lt;/li>
&lt;li>Support for Firefox is via Mozilla’s &lt;a href="https://github.com/mozilla/geckodriver/releases">geckodriver&lt;/a>.&lt;/li>
&lt;li>Support for Safari is provided on macOS (Sierra or later) via Apple’s own &lt;a href="https://developer.apple.com/library/prerelease/content/releasenotes/General/WhatsNewInSafari/Articles/Safari_10_0.html">safaridriver&lt;/a>.&lt;/li>
&lt;li>Support for Edge is provided by MS through their &lt;a href="https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/">webdriver server&lt;/a>.&lt;/li>
&lt;li>Only versions 9 or above of IE are supported. Earlier versions may work, but are no longer supported as &lt;a href="https://www.microsoft.com/en-gb/WindowsForBusiness/End-of-IE-support">MS no longer supports them&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>We’ll be posting more information about Selenium 3.0 to this blog soon, but until then if you’re interested in learning more then &lt;a href="https://www.youtube.com/watch?v=bistojJPR98">a recent webinar by Simon&lt;/a> is a great place to start.&lt;/p></description></item><item><title>Blog: IntelliJ</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2015/intellij/</link><pubDate>Sun, 08 Feb 2015 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2015/intellij/</guid><description>
&lt;p>Every year, Jetbrains are kind enough to donate an OSS license for IntelliJ to the Selenium project. As part of that process, they’ve asked that we review the product and (kudos to them!) have been clear that they hope we’re open and honest. So, I’ll be open and honest.&lt;/p>
&lt;p>When I tell people that I’m a professional Java developer, people in some circles make sympathetic noises and (sometimes) jokingly refer to how painful my coding life must be. After all, there are several far trendier and hipper languages, from Ruby, various flavours of Javascript, Python, Haskell, and even other languages running on the JVM such as Scala and Clojure. I tend to agree that Java is a relatively unexciting language as it’s generally practiced — Java 8 contains a wealth of goodies that lots of people won’t be using for years since they’ve still got to support Java 6(!) apps. Where I disagree with the detractors is that using Java is something to feel sorry for a developer for: Java on its own isn’t much fun, Java and IntelliJ is one of my favourite programming experiences.&lt;/p>
&lt;p>I’ve been using Java since the (very) late 90s, and have been using IntelliJ off-and-on since 2003 or so. In the intervening just-over-a-decade, what started as a tool that crossed the Rubicon of “being able to do refactoring” has matured. It has literally changed the way I write code: I now use the “Introduce Variable” refactoring to avoid needing to do initial assignments of values to variables as a matter of course. Indeed, with IntelliJ, I frequently stop thinking about the programming language and start thinking about the structure of the solution. Its refactorings make exploring large scale changes easy and entirely reliable, and once the restructurings are complete, I can jump to symbols with ease.&lt;/p>
&lt;p>Code exploration is aided by the simple and quick ways IntelliJ can find usages, and it’s simple to find unused code as method declarations get highlighted in a different shade to used ones. The integrated debugger is sufficiently capable that, coupled with unit tests, it’s normally pretty easy to figure out why some odd behaviour is happening. And, speaking of unit tests, the UI is clear and (I find) intuitive and easy to use.&lt;/p>
&lt;p>And those users of fancy-pants languages such as Clojure, Ruby, Python and Javascript (and PHP) can get plugins that extend IntelliJ’s capabilities and insight into those languages. Although it’s been a long time since I’ve had to deal with Spring and JEE, when I do IJ has my back, grokking the config files. The maven and gradle integration appears to work too, though Selenium uses CrazyFun and is migrating to Buck, so I’ve seldom any need to&lt;/p>
&lt;p>It’s not all wonder and joy. On large, multi-module codebases, IntelliJ seems to spend too long building caches. Activity Monitor on the Mac suggests it’s doing this in a single threaded manner, which is wasteful on a multicored machine. Switching away from IJ, doing something on the command line involving source control and then switching back is a sure-fire way to make it rebuild the caches, making it unresponsive. Extending IntelliJ by writing plugins is a black art — the documentation is scattered and appears out of date, making getting started on writing one hard.&lt;/p>
&lt;p>Overall, though, I love IntelliJ. On the Selenium project, it’s the IDE of choice, and I’ve been incredibly productive in it. Thank you, Jetbrains, for a wonderful tool.&lt;/p></description></item><item><title>Blog: Android and iOS Support</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/android-and-ios-support/</link><pubDate>Tue, 24 Dec 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/android-and-ios-support/</guid><description>
&lt;p>TL;DR: We’re retiring Selenium’s own AndroidDriver and iPhoneDriver in favour of any of &lt;a href="http://selendroid.io/">Selendroid&lt;/a>, &lt;a href="http://ios-driver.github.io/ios-driver/">iosdriver&lt;/a> and &lt;a href="http://appium.io/">Appium&lt;/a>. If you’re using one of Selenium’s own mobile drivers, please evaluate one of these alternatives.&lt;/p>
&lt;p>The longer version:&lt;/p>
&lt;p>In 2007, Steve Jobs &lt;a href="http://www.apple.com/pr/library/2007/01/09Apple-Reinvents-the-Phone-with-iPhone.html">announced the iPhone&lt;/a> and changed the mobile Web from a curiosity to something the mainstream wanted and used. Current trends suggest that mobile Web usage will surpass desktop usage in the not too distant future. Which is a long way of saying the mobile Web is going to be a big part of the future of your sites and that it’d be an extremely wise idea to test them on mobile devices.&lt;/p>
&lt;p>The Selenium project responded to the rise of the mobile web by working to produce WebDriver implementations for both iOS and Android. The first lines of the iPhoneDriver (which also worked on the iPad) were added to the project early in 2009. The AndroidDriver was added in June 2010, and was primarily developed by engineers at Google. To this day you can download the official Android SDK and find “&lt;a href="http://android-developers.blogspot.com/2011/10/introducing-android-webdriver.html">Google WebDriver&lt;/a>” as one of the optional extras you can download.&lt;/p>
&lt;p>After the initial work on the mobile drivers, something interesting happened. Experimental extensions and modifications to the drivers were made outside of the selenium project. The first one of these that I was involved with was “&lt;a href="https://code.google.com/p/nativedriver/">nativedriver&lt;/a>“. This took the novel approach of allowing users to interact with the native UI of the phone, be it Android or iOS, using the familiar WebDriver APIs. The first time I saw it, I thought it was madness, but the engineers working on it soon convinced me that it made sense. And guess what? They were right.&lt;/p>
&lt;p>Sadly, after proving the idea was viable and workable, the NativeDriver project ran out of steam, but it set the scene for three projects that have taken the idea and run with it to create remarkably capable pieces of mobile testing software: Selendroid, iosdriver and Appium. All three of these allow a tester familiar with the WebDriver APIs to test mobile apps on iOS and Android. Not only native ones, but also hybrid or pure web-based ones too. They’ve recently been joined by the &lt;a href="http://winphonewebdriver.codeplex.com/">Windows Phone WebDriver&lt;/a>, which allows testing of mobile web apps on WinPhone 8.&lt;/p>
&lt;p>All of these projects have something in common: they’re far more active, more capable and have pushed further than the equivalent code in the main selenium project. In fact, some of the members of the selenium team that contributed to both AndroidDriver and iPhoneDriver are now also working on those other projects. There’s &lt;a href="http://sauceio.com/index.php/2013/09/the-mobile-json-wire-protocol-workshop/">work being done&lt;/a> to &lt;a href="https://code.google.com/p/selenium/source/browse?repo=mobile">maintain interoperability&lt;/a> between the different drivers, allowing users to chose which framework is most appropriate for their needs without fear of their tests needing major rework.&lt;/p>
&lt;p>This means that keeping the existing Android and iPhone drivers within the Selenium project isn’t helping our users. The alternatives are better, and keeping “official” drivers within the project muddies the water. Worse, the selenium developers are slow at making fixes to those drivers, which is incredibly frustrating for everyone involved. Because of this, the Selenium project has deleted the code for those drivers from its repository and we recommend you evaluate and use one of the alternatives.&lt;/p>
&lt;p>Of course, the code will still live in our repo’s history, so if you’d like to build them yourself, then it’s still possible. The last version with the iPhoneDriver is &lt;a href="https://code.google.com/p/selenium/source/detail?r=ef9d5787e5e136ecb4a31b0cf53a1fd17e252cf3">ef9d578&lt;/a>, and the last one with the Android source is &lt;a href="https://code.google.com/p/selenium/source/detail?r=00a3c7df9fb4109e1f99b5f7bee5f5df74fb876a">00a3c7d&lt;/a>. We’ve uploaded a version of the AndroidDriver built from that revision to the downloads page to save you having to do so yourself.&lt;/p>
&lt;p>These changes do not mean that we don’t support mobile as a project. It just means that we support the best implementations of mobile WebDriver, and those aren’t written as part of the Selenium project.&lt;/p></description></item><item><title>Blog: Mobile WebDriver</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/mobile-webdriver/</link><pubDate>Wed, 28 Aug 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/mobile-webdriver/</guid><description>
&lt;p>Although the WebDriver APIs started life as just a mechanism for automating web browsers, over the past few years it has been extended to also work on mobile devices. Projects such as Appium, iosdriver, and Selendroid have all shown that this approach works, and works well. On the Web, if you start using Selenium WebDriver with one browser (Firefox, for example), it’s easy to switch out the browser for another one (such as Internet Explorer or Chrome). It’d be nice to have a similar option for mobile, switching from one automation framework for Android to another.&lt;/p>
&lt;p>As part of the Selenium 3 work, we have started working on a test suite to help ensure this level of interop between &lt;a href="http://appium.io/">appium&lt;/a> and &lt;a href="http://ios-driver.github.io/ios-driver/">iosdriver&lt;/a>, and appium and &lt;a href="http://selendroid.io/">selendroid&lt;/a>. To kick start the process, the primary authors of each of those tools, as well as others including David Burns representing the &lt;a href="https://developer.mozilla.org/en-US/docs/Marionette">Marionette&lt;/a> project (Mozilla’s implementation of WebDriver for Firefox and Firefox OS) and Simon Stewart, the lead of the &lt;a href="http://seleniumhq.org/">Selenium&lt;/a> project, have spent the past two days locked in a small room in Mozilla HQ, London. They’ve taken this time to work out the areas where each of their projects didn’t align and agreed on a way to ensure a level of interoperability. There was only a minimal quantity of blood and tears, but plenty of hard work.&lt;/p>
&lt;p>The &lt;a href="https://docs.google.com/document/d/1rnE13aGCaRiri01hti7j1jWDuPvQHT8aao4bHhEGz8Y/edit">agenda&lt;/a> for the past two days can be found here, and the &lt;a href="https://docs.google.com/document/d/1yXXsQo3z7lUVl3ZthAx39h4xBlF62x7q_NZd3NA9jnU/edit">minutes&lt;/a> are also available.&lt;/p>
&lt;p>As we speak, work has started on a shared test suite, hosted in a &lt;a href="https://code.google.com/p/selenium/source/checkout?repo=mobile">repo&lt;/a> in the selenium project’s Google Code page. Please, feel free to come along and join in!&lt;/p></description></item><item><title>Blog: The Road to Selenium 3</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/the-road-to-selenium-3/</link><pubDate>Wed, 28 Aug 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/the-road-to-selenium-3/</guid><description>
&lt;p>Selenium 2 was &lt;a href="http://seleniumhq.wordpress.com/2011/07/08/selenium-2-0/">released in July 2011&lt;/a>. It’s now two years old, and what a couple of years it’s been! The WebDriver APIs, which were the major addition in Selenium 2, are now the basis for a &lt;a href="http://www.w3.org/TR/webdriver/">W3C standard&lt;/a>, and there are implementations written and supported by Google, Mozilla and Opera. There have been 34 releases, with official support for Java, C#, Python, Ruby and Javascript, and the community has stepped in to provide bindings for Perl, PHP and others. There have been 57 different people authoring changes in the code base, and countless more participating in the online forums, offering help and advice.&lt;/p>
&lt;p>While all this has been happening, the world has moved on, and now it’s time for the Selenium project to look to the future. It’s with great pleasure that I can now say that we’re working towards Selenium 3.&lt;/p>
&lt;p>We aim for Selenium 3 to be “a tool for user-focused automation of mobile and web apps”.&lt;/p>
&lt;p>What does this mean? For mobile users, the Selenium project will be hosting a suite of tests to facilitate interoperability between the many different projects available that are extending the WebDriver API to also cope with mobile. Developers from projects such as &lt;a href="http://appium.io/">Appium&lt;/a>, &lt;a href="http://ios-driver.github.io/ios-driver/">ios-driver&lt;/a> and &lt;a href="http://selendroid.io/">selendroid&lt;/a> will be working on the suite of tests to enable this.&lt;/p>
&lt;p>We’ll also be working on making the technology behind Selenium as stable and capable as possible. For this reason, Selenium 3 will see the removal of the original Selenium Core implementations, and consequently we’ll be deprecating the RC APIs too. The old versions will still be available as a separate download, but active development will cease, except for very urgent fixes. We will still be providing an implementation of the RC APIs backed by WebDriver, so you can continue running your existing tests, but now would be a great time to make the move to using the WebDriver APIs directly.&lt;/p>
&lt;p>For those of you exporting your tests from IDE and running the HTML suites, we’ll provide an alternative runner that allows you to continue running those tests too, though it’ll be backed by the same “WebDriver-backed” RC implementation as offered by the main download. Again, the original implementation will be available as a download, but it will no longer be actively developed once we release 3.0.&lt;/p>
&lt;p>Our current plan is to start shipping 3.0 by Christmas this year: it’s going to be a lot of fun!&lt;/p></description></item><item><title>Blog: A Smattering of Selenium #157</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-157/</link><pubDate>Sun, 18 Aug 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-157/</guid><description>
&lt;p>Trying to find every excuse not to cut the grass … including apparently closing some browser tabs.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://idtus.com/blog/interoperability-standardized-test-information-interchange/">Interoperability – Standardized Test Information Interchange&lt;/a> has me so full of ‘meh’ as to be hilarious. Commercially driven standards rarely are and/or I am just too much of an open source person to accept this model for standards development&lt;/li>
&lt;li>&lt;a href="http://lucumr.pocoo.org/2013/7/23/licensing/">Licensing in a Post Copyright World&lt;/a> – important&lt;/li>
&lt;li>&lt;a href="https://segment.io/blog/how-to-make-async-requests-in-php/">How to Make Async Requests in PHP&lt;/a> is php specific in its solution, but has some interesting bits about socket establishment that applies to other ones as well&lt;/li>
&lt;li>&lt;a href="http://fadefade.com/json-comments.html">Adding Comments to JSON&lt;/a> feels like a hack. Buts a clever hack.&lt;/li>
&lt;li>&lt;a href="http://axelfontaine.com/blog/final-nail.html">Maven Release Plugin: The Final Nail in the Coffin&lt;/a> takes great joy in removing part of the maven environment from their workflow. And really, who doesn’t?&lt;/li>
&lt;li>&lt;a href="http://www.jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/">Open Sourcing a Python Project the Right Way&lt;/a> is nice … though of course, as with everything else these days, it has some Github specific isms. You &lt;em>can&lt;/em> do it the right way with hg and bitbucket of course… and that is disclaimed in the article&lt;/li>
&lt;li>&lt;a href="http://ihaztehcodez.michael-lloyd-lee.me.uk/2013/07/headless-watir.html">Headless Watir&lt;/a> using both HTTPUnit and PhantomJS&lt;/li>
&lt;li>&lt;a href="http://jimevansmusic.blogspot.ca/2013/08/implementing-http-status-codes-in.html">Implementing HTTP Status Codes in WebDriver, Part 2: Achievement Unlocked&lt;/a> – umm, part 2?&lt;/li>
&lt;li>&lt;a href="http://selenium34.wordpress.com/2013/08/14/phantomjs-plugins-aws-browsermob-proxy/">PhantomJS + Plugins + AWS + BrowserMob Proxy&lt;/a> – proxy all the things! Including headless things.&lt;/li>
&lt;li>&lt;a href="http://teddziuba.com/post/58003369831/mastering-the-craft">Mastering the Craft&lt;/a> is a good reminder, but also, eBay has its own customized version of eclipse? Guessing this is one of those ‘at scale’ solutions&lt;/li>
&lt;/ul></description></item><item><title>Blog: A Smattering of Selenium #156</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-156/</link><pubDate>Mon, 12 Aug 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-156/</guid><description>
&lt;p>Brain fried from PyCon Canada 2013 and ‘some’ browser tab is misbehaving which means its time to start closing some of these.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://antecedent.github.io/patchwork/">Patchwork&lt;/a> seems like an awesome idea, but at the same time, I’ve had to work in heavily monkey-patched RoR apps before…&lt;/li>
&lt;li>&lt;a href="https://igor.io/2013/07/26/evolving-syntax.html">Evolving syntax&lt;/a> is PHP specific in its examples, but the ideas transfer&lt;/li>
&lt;li>&lt;a href="http://adaptengine.com/blog/2013/07/24/roslyn-plus-selenium-scripty-csharp-powering-browser-automation/">Roslyn + Selenium: Scripty C# Powering Browser Automation&lt;/a> – some C# voodoo?&lt;/li>
&lt;li>&lt;a href="http://dnlkntt.wordpress.com/2013/08/07/its-like-10000-knives-when-all-you-need-is-a-spoon/">It’s like 10000 knives when all you need is a Spoon&lt;/a> – or specifically, this particular spoon which is yet-another-android-automation-tool. See comments for a bit of discussion re Appium which seems to be the currently best marketed solution in this space&lt;/li>
&lt;li>&lt;a href="http://www.diku.dk/hjemmesider/ansatte/torbenm/Planet/">Planet generator&lt;/a> has absolutely nothing to do with automation, but is just cool&lt;/li>
&lt;li>&lt;a href="http://www.testspicer.com/">TestSpicer&lt;/a> could be cool if it is massively flushed out&lt;/li>
&lt;li>&lt;a href="http://msdn.microsoft.com/en-us/library/ie/bg182625(v=vs.110).aspx">Compatibility changes in IE11 Preview&lt;/a> is going to break things I fear, for instance the readyState stuff?&lt;/li>
&lt;li>&lt;a href="https://speakerdeck.com/pyconca">PyCon Canada 2013 decks&lt;/a> are now up&lt;/li>
&lt;li>&lt;a href="http://jimevansmusic.blogspot.ca/2013/08/implementing-webdriver-http-status.html">Implementing WebDriver HTTP Status Codes, Part 1: Challenge Accepted&lt;/a> – is interesting in that it uses Fiddler&lt;/li>
&lt;li>&lt;a href="http://www.karlgroves.com/2013/05/14/links-are-not-buttons-neither-are-divs-and-spans/">Links are not buttons. Neither are DIVs and SPANs&lt;/a> – this, a million times.&lt;/li>
&lt;/ul></description></item><item><title>Blog: The World’s Best Selenium Meetup</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/the-worlds-best-selenium-meetup/</link><pubDate>Fri, 09 Aug 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/the-worlds-best-selenium-meetup/</guid><description>
&lt;p>Note from Adam: This is a guest post from &lt;a href="https://github.com/tourdedave">Dave Haeffner&lt;/a> who, along with &lt;a href="http://www.theautomatedtester.co.uk/">David Burns&lt;/a> hatched this idea at SeConf2013.&lt;/p>
&lt;h3 id="selenium-meetups-are-great-but">&lt;strong>Selenium Meetups are great, but…&lt;/strong>&lt;/h3>
&lt;p>Have you ever wanted to attend a Selenium Meetup but there’s not one near you? Or maybe there is but something’s come up and you can’t make it out that night? Or maybe the meetup near you struggles to get good speakers and have a consistent schedule? [Note from Adam; like, say, the Toronto one…]&lt;/p>
&lt;h3 id="we-can-do-better">&lt;strong>We can do better&lt;/strong>&lt;/h3>
&lt;p>Well, what if there were a way to attend a meetup regardless of location?&lt;/p>
&lt;p>And what if each meetup you attended was lined with core maintainers of the Selenium project?&lt;/p>
&lt;p>And if you missed it, what if the whole thing was recorded and available for you to review at your leisure?&lt;/p>
&lt;p>Well, now you can.&lt;/p>
&lt;h3 id="the-worlds-best-selenium-meetup">&lt;strong>The World’s Best Selenium Meetup&lt;/strong>&lt;/h3>
&lt;p>Introducing Selenium Hangout — the world’s best and most accessible Selenium meetup. An entirely online meetup that leverages Google Hangouts and live streaming to YouTube. All meetups will be recorded and posted online afterwards.&lt;/p>
&lt;p>Each meetup will contain a small panel of people from the Selenium Community (e.g. core committers, automation practitioners, etc.) and they will discuss various topics (TBD).&lt;/p>
&lt;h3 id="how-to-attend">&lt;strong>How to attend&lt;/strong>&lt;/h3>
&lt;p>Simply follow &lt;a href="https://twitter.com/SeleniumHangout">the SeleniumHangout Twitter account&lt;/a> to find out more.&lt;/p></description></item><item><title>Blog: A Smattering of Selenium #155</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-155/</link><pubDate>Sun, 28 Jul 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-155/</guid><description>
&lt;p>A ‘should be scripting, but brain stuck in neutral so closing some tabs’ edition of the Smattering.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://www.90percentofeverything.com/2013/07/23/the-slippery-slope/">The slippery slope&lt;/a> isn’t automation related, but if your employer does these things I’d suggest logging a bug and then finding an ethical job&lt;/li>
&lt;li>&lt;a href="https://caremad.io/blog/packaging-signing-not-holy-grail/">Why Package Signing is not the Holy Grail&lt;/a> – crypto / security is hard. Also, I have a signed package for you to install…&lt;/li>
&lt;li>&lt;a href="http://blog.preinheimer.com/index.php?/archives/416-PHP-and-Async-requests-with-file-based-sessions.html">PHP and Async requests with file based sessions&lt;/a> could be a way to speed up a PHP site. Which in turn reduces the amount of time your scripts take to run&lt;/li>
&lt;li>&lt;a href="http://canadipsum.com/">Canadipsum, eh?&lt;/a> just because. (eh)&lt;/li>
&lt;li>&lt;a href="http://blogs.infosupport.com/using-codedui-testautomation-without-uimap-files/">Using CodedUI testautomation without UIMap files&lt;/a> brings Page Objects to CodedUI&lt;/li>
&lt;li>&lt;a href="http://blog.matthewskelton.net/2013/07/22/continuous-delivery-workshop-with-neal-ford-neal4d-a-retrospective/">Continuous Delivery Workshop With Neal Ford (@Neal4D) – a Retrospective&lt;/a> – yup, the hard part is not the technical bit, but the people parts&lt;/li>
&lt;li>&lt;a href="http://librarian-puppet.com/">librarian-puppet&lt;/a> says &lt;em>You can all stop using git submodules now&lt;/em> which is good enough for me&lt;/li>
&lt;li>&lt;a href="http://swdandruby.wordpress.com/2013/07/26/highlighting-the-element-before-any-clicks-a-foray-into-the-abstracteventlistener/">Highlighting the element before any clicks: A foray into the AbstractEventListener&lt;/a> — the event listener stuff is something I need to sort out.&lt;/li>
&lt;li>&lt;a href="http://www.phptesting.org/">phpci&lt;/a> is built specifically for php apps, and doesn’t pretend to have the features something like jenkins does&lt;/li>
&lt;li>&lt;a href="http://words.steveklabnik.com/beware-subclassing-ruby-core-classes">Beware subclassing Ruby core classes&lt;/a> – there are likely parallels in other languages as well.&lt;/li>
&lt;/ul></description></item><item><title>Blog: A Smattering of Selenium #154</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-154/</link><pubDate>Tue, 23 Jul 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-154/</guid><description>
&lt;p>Apparently today’s ‘wait for an email’ task is to whittle down the smattering queue some more.&lt;/p>
&lt;ul>
&lt;li>I won’t even pretend that &lt;a href="http://foaas.com/">FOAAS&lt;/a> has to do with automation, but makes me laugh. Also, depending on how crappy your place of work is, it might not be SFW&lt;/li>
&lt;li>&lt;a href="https://wiki.php.net/rfc/use_function">PHP RFC: Importing namespaced functions&lt;/a> is interesting if you are writing your scripts in a Functional manner. In PHP. In a future where it gets accepted and implemented.&lt;/li>
&lt;li>&lt;a href="http://www.webperformance.com/load-testing/blog/2013/05/measuring-web-page-load-times-using-jmeter/">Measuring Web Page Load Times using JMeter&lt;/a> — and read the response articles too for clarification / elaboration&lt;/li>
&lt;li>I kinda like that Se suites are making their way into large projects such as &lt;a href="https://github.com/moodlehq/functional-test-suite">Moodle’s functional-test-suite repo&lt;/a>. But at the same time it worries me when it hasn’t had a commit in 10 months. Suites should likely change even more than the app code it exercises&lt;/li>
&lt;li>&lt;a href="http://searls.testdouble.com/posts/2013-03-21-jasmine-tactics-screencast.html">jasmine tactics screencast&lt;/a> — on the long list of tools I should learn&lt;/li>
&lt;li>&lt;a href="http://blog.mogotest.com/2013/03/25/introducing-the-mogotest-jenkins-plugin/">Introducing the Mogotest Jenkins Plugin&lt;/a> – hurray for more pipeline integration points&lt;/li>
&lt;li>&lt;a href="http://blog.korynunn.com/javascript/the-dom-isnt-slow-you-are/">The DOM isn’t slow, you are.&lt;/a> — set the phasers on snark, and then read it anyways.&lt;/li>
&lt;li>&lt;a href="http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/">Cross-Browser, Event-based, Element Resize Detection&lt;/a> – edges are sharp.&lt;/li>
&lt;li>&lt;a href="http://www.copyblogger.com/social-media-marketing-roi/">There is No ROI in Social Media Marketing&lt;/a> – read this, and now read it again swapping in Functional Automation everywhere&lt;/li>
&lt;li>&lt;a href="http://hellogeri.com/blog/view/now_available_pocket_guide_to_colour_accessibility">Now Available: Pocket Guide to Colour Accessibility&lt;/a> could, in theory, be translated into a set of ‘rules’ to validate pages against since we can the colour of elements and their computed css values.&lt;/li>
&lt;/ul></description></item><item><title>Blog: A Smattering of Selenium #153</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-153/</link><pubDate>Mon, 22 Jul 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-153/</guid><description>
&lt;p>A Sunday Smattering? Sure!&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://blog.reallysimplethoughts.com/2013/07/14/solution-to-the-selenium-with-firefox-22-issues-and-how-to-report-issues/">Solution to the Selenium with Firefox 22 Issues and How to Report Issues&lt;/a> – Open Source is hard. Supporting Open Source’s infrastructure is harder — by a large margin&lt;/li>
&lt;li>&lt;a href="https://github.com/i-trofimtschuk/frequests">frequests&lt;/a> – asyncronous HTTP Requests; not sure where I would use this, but…&lt;/li>
&lt;li>&lt;a href="http://pilif.github.io/2013/07/why-I-dont-touch-crypto/">why I don’t touch crypo&lt;/a> – again, don’t. touch. crypto&lt;/li>
&lt;li>&lt;a href="http://www.webdirections.org/blog/five-reasons-why-you-should-quote-attribute-values-in-html5">Five reasons why you should quote attribute values in HTML5&lt;/a> – for the record, you should do this in HTML 4 as well.&lt;/li>
&lt;li>&lt;a href="http://www.youtube.com/playlist?list=PLmV2D6sIiX3UpQFzAIWh-_gsUTGCCtFIj">All the ‘Write The Docs session videos&lt;/a> — a conference I couldn’t afford to attend, and likely don’t have the time to watch the videos now&lt;/li>
&lt;li>&lt;a href="http://blog.chariotsolutions.com/2013/07/automated-testing-of-html5-canvas.html">Automated Testing of HTML5 Canvas Applications with Selenium WebDriver&lt;/a> – more and more important…&lt;/li>
&lt;li>&lt;a href="http://swdandruby.wordpress.com/2013/07/12/solving-window-onbeforeunload-nasty-prompts/">Solving window.onbeforeunload nasty prompts&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://pypi.python.org/pypi/pytest-poo">pytest-poo&lt;/a> for when your tests are, erm, crappy&lt;/li>
&lt;li>&lt;a href="http://ljouanneau.com/blog/post/2013/07/15/Tada-Here-is-SlimerJS">Tada! Here is SlimerJS!&lt;/a> – like PhantomJS but for Gecko. I think.&lt;/li>
&lt;li>&lt;a href="http://swdandruby.wordpress.com/2013/07/19/did-i-select-the-right-element/">Did I select the right element?&lt;/a> is a neat trick for highlighting things — even if the escaping of the code didn’t seem to survive formatting&lt;/li>
&lt;/ul></description></item><item><title>Blog: A Smattering of Selenium #152</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-152/</link><pubDate>Thu, 11 Jul 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-152/</guid><description>
&lt;p>40-ish minutes until midnight eastern so that counts as two days in a row, right? Right?&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://tobiasgeyer.wordpress.com/2013/07/04/improving-jenkins-execution-times-by-common-sense/">Improving jenkins execution times by common sense&lt;/a> — common sense. sadly lacking most days.&lt;/li>
&lt;li>&lt;a href="http://www.testinggeek.com/how-to-make-test-automation-more-effective">How to make test automation more effective?&lt;/a> is useful up until the pitch at the end. So read until you get to that.&lt;/li>
&lt;li>&lt;a href="http://phpmaster.com/data-structures-2/">Data Structures for PHP Devs: Trees&lt;/a> – non-trivial data structures are non-trivial&lt;/li>
&lt;li>&lt;a href="http://c089.wordpress.com/2013/07/06/writing-clean-webdriver-test-suites-for-duplicate-functionality-by-parameterizing-on-page-objects/">Writing clean WebDriver test suites for “duplicate” functionality by parameterizing on page objects&lt;/a> – I especially like the usage of ‘might’ at the top&lt;/li>
&lt;li>&lt;a href="https://npmjs.org/package/dalek-internal-webdriver">dalek-internal-webdriver&lt;/a> – what’s a day without a JS webdriver implementation?&lt;/li>
&lt;li>&lt;a href="http://www.html5rocks.com/en/tutorials/internals/antialiasing-101/">Antialiasing 101&lt;/a> – I kinda think that automators should just spend a day reading this site rather than reddit&lt;/li>
&lt;li>&lt;a href="http://myronmars.to/n/dev-blog/2013/07/rspec-2-14-is-released">RSpec 2.14 is released!&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://www.chmod777self.com/2013/07/http2-status-update.html">HTTP/2 Status Update&lt;/a> – Ugh.&lt;/li>
&lt;li>&lt;a href="http://thephp.cc/viewpoints/blog/2013/07/php-5-5-generators">PHP 5.5: Generators&lt;/a> – You know, with yesterday’s phpenv I’m almost tempted to make some of my stuff PHP 5.5…&lt;/li>
&lt;li>&lt;a href="http://arrgyle.com/blog/program-like-a-machinist/">Program Like a Machinist&lt;/a> – hurray for understanding the motorcycle example!&lt;/li>
&lt;/ul></description></item><item><title>Blog: A Smattering of Selenium #151</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-151/</link><pubDate>Wed, 10 Jul 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-151/</guid><description>
&lt;p>Almost a month after the last one. Though it did nice to have it at 150 when people go to the blog … but a greater number is nicer.&lt;/p>
&lt;ul>
&lt;li>So I was trying to find &lt;a href="http://requests.ryanmccue.info/">Requests for PHP&lt;/a> whilst talking to &lt;a href="http://grumpy-phpunit.com/">the grumpy programmer&lt;/a> and he pointed me out to &lt;a href="http://guzzlephp.org/index.html">Guzzle&lt;/a> which looks equally cool&lt;/li>
&lt;li>&lt;a href="http://stupidpythonideas.blogspot.com.au/2013/06/can-you-optimize-listgenexp.html">Can you optimize list(genexp)&lt;/a> is one of those geeky language internals things that could be handy to have in your back pocket&lt;/li>
&lt;li>&lt;a href="http://simplythetest.tumblr.com/post/54558598766/slightly-snarky-gwt-debug-id-faq">Slightly Snarky GWT Debug ID FAQ&lt;/a> – c’mon, when have you seen a more blatantly ‘put this in the smattering’ title than this?&lt;/li>
&lt;li>&lt;a href="https://github.com/CHH/phpenv">phpenv&lt;/a> could be useful. And could be I mean ‘holy crap this is useful’ — but then again, I do actually need 3 different versions of PHP locally. YMMV&lt;/li>
&lt;li>&lt;a href="http://oneandonemakesthreeright.blogspot.be/2013/06/pain-killing-pingpongers-decease.html">Pain killing the pingponger’s decease&lt;/a> is by their own admission not stable, but is a nice temporary solution. And illustrates why you should learn your tools — if they didn’t know about custom annotations and their runners in JUnit they would have missed this.&lt;/li>
&lt;li>Yet another JS testing framework has grown a webdriver tentacle – &lt;a href="https://github.com/karma-runner/karma-webdriver-launcher">karma-webdriver-launcher&lt;/a>&lt;/li>
&lt;li>I barely understand a word of &lt;a href="https://github.com/raganwald/homoiconic/blob/master/2012/08/method-decorators-and-combinators-in-coffeescript.md#method-combinators-in-coffeescript">Method Combinators in CoffeeScript&lt;/a> which is often a sign I should include something&lt;/li>
&lt;li>&lt;a href="http://bigqueri.es/t/how-are-javascript-files-being-served-and-how-many-are-there/36">How are JavaScript files being served and how many are there?&lt;/a> is interesting … even if I don’t understand what/where he has put all this HAR information so one could reproduce this on their one data&lt;/li>
&lt;li>&lt;a href="http://andrewkelley.me/post/jamulator.html">Statically Recompiling NES Games into Native Executables with LLVM and Go&lt;/a> – $entity help us if we ever need to do this level of ridiculousness to drive browsers, but holy wow its cool.&lt;/li>
&lt;li>Remember I said I should just auto-include all of Raymond Hettinger’s SO answers? Well, here’s another one – &lt;a href="http://stackoverflow.com/questions/17006127/python-importing-class-attributes-into-method-local-namespace/17006268#17006268">Python importing class attributes into method local namespace&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Blog: A Smattering of Selenium #150</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-150/</link><pubDate>Fri, 14 Jun 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-150/</guid><description>
&lt;p>Yup, this smattering has very little to do with Selenium, but… 150!&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://blog.pamelafox.org/2013/06/referencing-dom-from-js-there-must-be.html">Referencing DOM from JS: there must be a DRYer, safer way&lt;/a> is a nice ‘here is where I started, and here is how I ended up where I am’ post which can be stolen into other languages / frameworks other than in Backbone&lt;/li>
&lt;li>&lt;a href="https://blog.engineyard.com/2013/hash-lookup-in-ruby-why-is-it-so-fast">Hash lookup in Ruby, why is it so fast?&lt;/a> is not something I was wondering, but now I know why.&lt;/li>
&lt;li>&lt;a href="http://www.jstorimer.com/blogs/workingwithcode/8100871-nobody-understands-the-gil-part-2-implementation">Nobody understands the GIL&lt;/a> – in any language.&lt;/li>
&lt;li>&lt;a href="https://groups.google.com/forum/#!msg/php-fig/WMaKNNhHZJw/Waib99Zzf68J">Resource Locator Discussion&lt;/a> – namespace all the things!&lt;/li>
&lt;li>&lt;a href="http://dhemery.com/pdf/test-automation-zombie-apocalypse.pdf">How to Survive the Coming Test Automation Zombie Apocalypse&lt;/a> is abso-freaking-lutely awesome&lt;/li>
&lt;li>&lt;a href="https://gist.github.com/dimacus/5757573">Blackhole proxy to block all external calls&lt;/a> is a snippet that came out of SeConf this week&lt;/li>
&lt;li>&lt;a href="http://nedbatchelder.com/blog/201306/filter_a_list_into_two_parts.html">Filter a list into two parts&lt;/a>. Ouch. My brain just broke. (But generators do that to me.)&lt;/li>
&lt;li>&lt;a href="http://www.amazon.com/about-dates-times-computing-ebook/dp/B00DCJZDYE/">What you need to know about dates and times in computing&lt;/a> could be useful. If one kindles.&lt;/li>
&lt;li>&lt;a href="https://gist.github.com/wolever/5762823">SSL Helpers&lt;/a> is a couple python scripts for manipulating certificates&lt;/li>
&lt;li>&lt;a href="http://storyautomation.com/">storyautomation&lt;/a> seems to have a number of decent posts. Of course, they are around RC so I was hesitant to link to it, but it looks like the ideas could transpose up to WebDriver&lt;/li>
&lt;/ul></description></item><item><title>Blog: A Smattering of Selenium #149</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-149/</link><pubDate>Wed, 05 Jun 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-149/</guid><description>
&lt;p>Too. Many. Tabs.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://watirmelon.com/2013/05/30/internationalization-and-localization-testing/">Internationalization and Localization Testing&lt;/a> — yup, I agree.&lt;/li>
&lt;li>&lt;a href="http://daker.me/2013/05/5-html5-features-you-need-to-know.html">5 HTML5 Features you need to know&lt;/a> – ‘download attribute’ and ‘datalist element’ might be a pain for us automators. Or at least cause a couple hours annoyance until we figure out the pattern.&lt;/li>
&lt;li>&lt;a href="http://minds.coremedia.com/2013/06/03/death-to-sleeps-raise-of-conditions/">Death to sleeps! Raise of Conditions!&lt;/a> – expected conditions is likely the next thing to get more marketing this year&lt;/li>
&lt;li>&lt;a href="http://pythonhosted.org/line_profiler/">line_profiler and kernprof&lt;/a> – profiling is black magic voodoo&lt;/li>
&lt;li>&lt;a href="https://github.com/avdi/naught">Naught&lt;/a> – ‘Naught is a toolkit for building Null Objects in Ruby.’&lt;/li>
&lt;li>&lt;a href="http://stackoverflow.com/questions/10436454/replacing-a-substring-of-a-string-with-python/10436832">Replacing a substring of a string with Python&lt;/a> – Raymond’s answers always simultaneously break my break and blow my mind.&lt;/li>
&lt;li>&lt;a href="http://stackoverflow.com/questions/16645083/when-splitting-an-empty-string-in-python-why-does-split-return-an-empty-list/16645307">When splitting an empty string in Python, why does split() return an empty list while split(‘\n’) returns [”]?&lt;/a> – see what I mean?&lt;/li>
&lt;li>&lt;a href="http://element34.ca/blog/so-you-want-to-build-a-framework">So you want to build a framework&lt;/a> – mine, but important. (I think.)&lt;/li>
&lt;li>&lt;a href="http://adit.io/posts/2013-05-15-Locks,-Actors,-And-STM-In-Pictures.html">Locks, Actors, And STM In Pictures&lt;/a> – ya! pictures!&lt;/li>
&lt;li>&lt;a href="http://watirmelon.com/2013/05/14/packaging-a-ruby-script-as-an-windows-exe-using-ocra/">Packaging a ruby script as an Windows exe using OCRA&lt;/a> looks like something useful&lt;/li>
&lt;/ul></description></item><item><title>Blog: A Smattering of Selenium #148</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-148/</link><pubDate>Mon, 13 May 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-148/</guid><description>
&lt;p>Gotta start this up again…&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.google.com/presentation/d/1zImieKjgfF2mvTEfLhkKnJpBrsq-shMWz1DMb-fxOoQ/edit#slide=id.gc15489c2_3_0">The Evil Tester Guide To HTTP Proxies&lt;/a> appears to be more for using proxies for manual testing, but you &lt;em>should&lt;/em> be running your automation through one as well so it helps to understand the magic that takes place.&lt;/li>
&lt;li>New &lt;a href="http://bmp.lightbody.net/">BrowserMob Proxy&lt;/a> release. Bindings should all be updated for the newly exposed methods in a couple days.&lt;/li>
&lt;li>&lt;a href="http://flippinawesome.org/2013/05/06/5-things-you-should-stop-doing-with-jquery/#__sid=0">5 Things You Should Stop Doing With jQuery&lt;/a> – Not sure whats better, the content, or the Saved By The Bell theme&lt;/li>
&lt;li>&lt;a href="https://pypi.python.org/pypi/testtools">testtools&lt;/a> is the latest hotness in the world of Python runners?&lt;/li>
&lt;li>&lt;a href="https://github.com/d11wtq/boris">Boris&lt;/a> looks pretty useful for the PHP folks&lt;/li>
&lt;li>&lt;a href="http://paulhammant.com/2013/05/06/googles-scaled-trunk-based-development/">Google’s Scaled Trunk Based Development&lt;/a> – even if you are not Google, you should be doing this. Or as much as you can (again, you are likely not Google)&lt;/li>
&lt;li>&lt;a href="http://artsy.github.io/blog/2012/02/03/reliably-testing-asynchronous-ui-w-slash-rspec-and-capybara/">Reliably Testing Asynchronous UI W/ RSpec and Capybara&lt;/a> isn’t new, but the &lt;em>wait_for_dom&lt;/em> thing is new [to me]&lt;/li>
&lt;li>&lt;a href="http://www.holovaty.com/writing/in-defense-of-canvas/">In defense of &lt;canvas>&lt;/a> – canvas worries me&lt;/li>
&lt;li>&lt;a href="http://filipin.eu/one-does-not-simply-set-profile-for-remote-chrome/">One Does Not Simply Set Profile for Remote Chrome&lt;/a> is Watir, but links to the pure WebDriver in SO article. I don’t think any of the other bindings deliver chrome profiles over the wire…&lt;/li>
&lt;li>&lt;a href="https://github.com/moodlehq/functional-test-suite">The Moodle Functional Test Automation Harness&lt;/a> – always fun to peek into other’s suites&lt;/li>
&lt;/ul></description></item><item><title>Blog: A Smattering of Selenium #147</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-147/</link><pubDate>Thu, 14 Mar 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-147/</guid><description>
&lt;p>My. Get. Productive. I know! I’ll push out a smattering. Oh. …&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://speakerdeck.com/mleone/python-for-ruby-programmers">Python for Ruby Programmers&lt;/a> is a pretty good deck, with the requisite snark at the end that you can safely ignore.&lt;/li>
&lt;li>&lt;a href="http://blog.ivandemarino.me/2013/03/03/Me-Selenium-Camp-2013">Me @ Selenium Camp 2013&lt;/a> is Ivan’s mini-experience-report from SeCamp and has his slides on GhostDriver&lt;/li>
&lt;li>Using pip in production? &lt;a href="http://tartley.com/?p=1423">pip install : Lightspeed and Bulletproof&lt;/a> is a useful trick which I know I’ve done variants of with java and ruby in the past&lt;/li>
&lt;li>&lt;a href="http://www.seleniumconf.org/speakers/">SeConf speakers are up&lt;/a> — and the list looks really good&lt;/li>
&lt;li>&lt;a href="http://www.brandonsavage.net/interfaces-or-abstract-classes/">Interfaces or Abstract Classes?&lt;/a> is marketing fodder, but its the best kind of fodder since its actually useful. For those of us still working through PHP.&lt;/li>
&lt;li>I forgot about this semantic war in the whole three weeks since it happened…
&lt;ul>
&lt;li>&lt;a href="http://context-driven-testing.com/?p=69">The Insapience of Anti-Automationism&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://www.developsense.com/blog/2013/02/manual-and-automated-testing/">“Manual” and “Automated” Testing&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://xprogramming.com/articles/manual-testing-does-exist-and-it-is-bad/">Manual Testing Does Exist and It Is Bad&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://carstenfeilberg.blogspot.dk/2013/03/my-two-on-opposite-terms.html">My two € on opposite terms&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="https://speakerdeck.com/mathieu_calba/android-ui-design-pattern-in-practice-english-version">Android UI Design Pattern in practice&lt;/a> is not only useful, but I like the format…&lt;/li>
&lt;li>&lt;a href="http://www.slideshare.net/mikebrittain/mbrittain-continuous-deploymentalm3public">Continuous Deployment: The Dirty Details&lt;/a> – slide 18, 36, 42, 83, 102 are the killer slides. 102 is the killer-est slide and is where I would enter a semantic debate with the fine folks at Etsy over whether they are doing Continuous Deployment or Continuous Delivery&lt;/li>
&lt;li>&lt;a href="http://www.theautomatedtester.co.uk/blog/2013/could-css3-be-making-sites-that-are-not-testable.html">Could CSS3 be making sites that are not testable?&lt;/a> – New standards making the life of automators more incredibly hard? Never!&lt;/li>
&lt;li>&lt;a href="http://coreygoldberg.blogspot.ca/2013/01/python-verify-png-file-and-get-image.html">Python – verify a PNG file and get image dimensions&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Blog: A Smattering of Selenium #146</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-146/</link><pubDate>Mon, 11 Mar 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-146/</guid><description>
&lt;p>Happy ‘productivity destructive week’ — otherwise known as March break.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://blog.mogotest.com/2013/03/05/how-to-accept-self-signed-ssl-certificates-in-selenium2/">How to Accept Self-Signed SSL Certificates in Selenium 2&lt;/a> — or you could use ‘real’ certificates that are trusted by the browser by default. If you are using self-signed certificates to ‘save money’ and you spend 3 hours making it work, you are not saving money anymore&lt;/li>
&lt;li>&lt;a href="https://github.com/tcoulter/jockeyjs">JockeyJS&lt;/a> seems like it could be useful&lt;/li>
&lt;li>Dear every-js-widget-library-author, &lt;a href="http://www.nczonline.net/blog/2013/01/29/you-cant-create-a-button/">You can’t create a button&lt;/a>&lt;/li>
&lt;li>If you are using PHP, then &lt;a href="http://grumpy-phpunit.com/">The Grumpy Programmer’s PHPUnit Cookbook&lt;/a> should be added to your reading pile. Thankfully he doesn’t touch on the built-in WebDriver stuff but the ToC still looks relevant to what we do&lt;/li>
&lt;li>&lt;a href="http://blog.newrelic.com/2013/02/07/web-performance-optimization-automation/">WordPress Performance Optimization&lt;/a> is just cool — and could provide tricks for your non-WordPress apps too&lt;/li>
&lt;li>&lt;a href="http://blog.veez.us/single-session-development">Single-Session Development&lt;/a> is something I don’t do — but can appreciate the geek-ness of this&lt;/li>
&lt;li>&lt;a href="http://edmundkirwan.com/general/junit.html">JUnit’s evolving structure&lt;/a> shows what the, erm, evolving structure of JUnit and has the killer line of ‘Programmers should be forced to wear their systems’ package-structures on their tee-shirts.’&lt;/li>
&lt;li>&lt;a href="http://element34.ca/blog/basic-authentication-with-the-browsermob-proxy">Basic Authentication With the BrowserMob Proxy&lt;/a>, wow, that’s an annoying edge-case&lt;/li>
&lt;li>&lt;a href="http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown">Breaking Down Amazon’s Mega Dropdown&lt;/a> – ugh, because mouse events weren’t hard enough without menus tracking and rendering based on its position&lt;/li>
&lt;li>If you are intro RSpec, then &lt;a href="http://rspec-next-steps.herokuapp.com/">RSpec Next Steps&lt;/a> is going to be for you. Even if it does use a horrid html-based deck format (use the left/right arrow keys to navigate)&lt;/li>
&lt;/ul></description></item><item><title>Blog: A Smattering of Selenium #145</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-145/</link><pubDate>Mon, 04 Mar 2013 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2013/a-smattering-of-selenium-145/</guid><description>
&lt;p>&lt;a href="http://www.brothers-brick.com/2013/02/26/alice-finch-builds-massive-lego-hogwarts-from-400000-bricks/">Alice Finch builds massive LEGO Hogwarts from 400,000 bricks&lt;/a> starts out at awesome and goes somewhere further down the scale when you get to the photo that shows scale.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://exploringuncertainty.com/blog/archives/1010">Models of Automation&lt;/a> — really, who reading this hasn’t had the conversation described in there in one of its variants&lt;/li>
&lt;li>&lt;a href="http://ardesco.lazerycode.com/index.php/2013/02/stop-moving-so-i-can-click-you-dammit/">Stop Moving So I Can Click You Dammit!&lt;/a> – illustrates the only acceptable place for Thread.sleep()&lt;/li>
&lt;li>&lt;a href="http://blog.simontimms.com/2013/02/25/using-realistic-data-in-unit-testing/">Using Realistic Data in Unit Testing&lt;/a> and &lt;a href="http://blog.simontimms.com/2013/02/26/angelasmith-creating-test-data/">AngelaSmith: Creating Test Data&lt;/a> is a two-for for the C# crowd — though the ideas resonate with everyone else&lt;/li>
&lt;li>&lt;a href="http://www.testinggeek.com/test-automation-how-to-handle-common-components-with-page-object-model">How to handle common components with Page Object Model?&lt;/a> — I tend to use Inheritance, though am experimenting with Composition. The right solution is likely ‘both’&lt;/li>
&lt;li>&lt;a href="http://nic.ferrier.me.uk/blog/2013_02/dear-nic-says-jim">Dear Nic, Should we log directly?&lt;/a> illustrates the good and bad of unix pipes&lt;/li>
&lt;li>&lt;a href="http://stackoverflow.com/questions/10057671/how-foreach-actually-works/">How foreach actually works&lt;/a> was found via a snarky tweet, but is great&lt;/li>
&lt;li>&lt;a href="http://feross.org/fill-disk/">Introducing the HTML5 Hard Disk Filler&amp;amp;tm; API&lt;/a> is hilarious. And the next salvo in the WebKit vs mono-culture battle&lt;/li>
&lt;li>&lt;a href="http://www.html5rocks.com/en/tutorials/webcomponents/template/">HTML’s New Template Tag – Standardizing Client-Side Templating&lt;/a> — look! More HTML5 madness! And no automation suggestions / gotchas. But HTML5 Rocks is a great site anyways&lt;/li>
&lt;li>&lt;a href="http://watirmelon.com/2013/03/02/why-your-web-app-should-be-responsive/">Why your web app should be responsive&lt;/a> — I’m coming to dislike the term ‘responsive’, though agree with the sentiment. Now, how does your WebDriver [or Watir] scripts change in order to handle this?&lt;/li>
&lt;li>&lt;a href="http://mattsears.com/articles/2011/11/16/nyan-cat-rspec-formatter">Nyan Cat RSpec Formatter&lt;/a> is outstandlingly silly. And should be applied to all your RSpec runners. Immediately.&lt;/li>
&lt;/ul></description></item></channel></rss>