<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: endtest</title>
    <description>The latest articles on DEV Community by endtest (@endtest_io).</description>
    <link>https://dev.to/endtest_io</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F85212%2F31fd04db-d90b-46a7-ae0e-bf034b339d9b.png</url>
      <title>DEV Community: endtest</title>
      <link>https://dev.to/endtest_io</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/endtest_io"/>
    <language>en</language>
    <item>
      <title>How To Record Automated Tests For Mobile Apps </title>
      <dc:creator>endtest</dc:creator>
      <pubDate>Wed, 18 Mar 2020 13:48:00 +0000</pubDate>
      <link>https://dev.to/endtest/how-to-record-automated-tests-for-mobile-apps-4am5</link>
      <guid>https://dev.to/endtest/how-to-record-automated-tests-for-mobile-apps-4am5</guid>
      <description>&lt;p&gt;&lt;a href="https://endtest.io"&gt;Endtest&lt;/a&gt; allows you to create, manage and execute Automated Tests, without having to write any code. &lt;/p&gt;

&lt;p&gt;You can use the open-source &lt;a href="https://chrome.google.com/webstore/detail/endtest-codeless-automate/jbdgfkeimppmnfemmgfafiomihlibdfa"&gt;Endtest Chrome Extension&lt;/a&gt; to record a test for your website directly in the browser.&lt;/p&gt;

&lt;p&gt;But did you know that you can also record tests for native and hybrid Android and iOS applications? 🤗&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E8Lku-eM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2e8y5lrvmehbiefvx6ky.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E8Lku-eM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2e8y5lrvmehbiefvx6ky.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And you do that direcly from your browser.&lt;/p&gt;

&lt;p&gt;What? 😱&lt;/p&gt;

&lt;p&gt;That's right.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://endtest.io/guides/docs/how-to-create-mobile-tests/"&gt;Mobile Recorder&lt;/a&gt; allows you to record tests for native and hybrid mobile apps, directly in your browser. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What are the steps?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;You upload the APK or IPA file. &lt;/li&gt;
&lt;li&gt;The app is installed on a real mobile device.&lt;/li&gt;
&lt;li&gt;The information for each element is extracted.&lt;/li&gt;
&lt;li&gt;An interactive preview is shown in real-time in your browser window.&lt;/li&gt;
&lt;li&gt;You record the test. &lt;/li&gt;
&lt;li&gt;You save the test.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/4vqxABcfpac"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;But how does it locate the elements?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It's no secret that our engine for Mobile Tests is using &lt;a href="http://appium.io/"&gt;Appium&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We just fetch the locators for the elements that you interact with. &lt;/p&gt;

&lt;p&gt;If we would rely on image recognition, that would lead to brittle tests.&lt;/p&gt;

&lt;p&gt;We fetch the following locators:&lt;br&gt;
• ID&lt;br&gt;
• Accessibility ID&lt;br&gt;
• Name&lt;br&gt;
• Class Name&lt;br&gt;
• XPath&lt;br&gt;
• Coordinates&lt;/p&gt;

&lt;p&gt;If you're not using Coordinates, you can easily execute the same test on different devices.&lt;/p&gt;

&lt;p&gt;Coordinates are only used in extreme cases, when no other unique locator is available.&lt;/p&gt;

&lt;p&gt;You can find more details in our &lt;a href="https://endtest.io/guides/docs/how-to-create-mobile-tests/"&gt;Documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>mobile</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>Building The Most Powerful Test Recorder On The Market</title>
      <dc:creator>endtest</dc:creator>
      <pubDate>Fri, 21 Feb 2020 15:09:14 +0000</pubDate>
      <link>https://dev.to/endtest/building-the-most-powerful-test-recorder-on-the-market-5ggd</link>
      <guid>https://dev.to/endtest/building-the-most-powerful-test-recorder-on-the-market-5ggd</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://endtest.io"&gt;Endtest&lt;/a&gt; allows you to create, manage and execute Automated Tests, without having to write any code. &lt;/p&gt;

&lt;p&gt;You can use the &lt;a href="https://chrome.google.com/webstore/detail/endtest-codeless-automate/jbdgfkeimppmnfemmgfafiomihlibdfa"&gt;Endtest Chrome Extension&lt;/a&gt; to record a test directly in the browser.&lt;/p&gt;

&lt;p&gt;And yes, it's open-source and free to use. 🤗&lt;/p&gt;

&lt;p&gt;This extension works by recording all the steps that a user performs in the browser and converts those steps into an automated test.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/cFboO4O5moU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. How we record the steps&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We record the following actions:&lt;br&gt;
• Click&lt;br&gt;
• Right Click&lt;br&gt;
• Write Text&lt;br&gt;
• Select option from dropdown&lt;br&gt;
• Press Key&lt;br&gt;
• Hover&lt;br&gt;
• Scroll&lt;br&gt;
• Open tab&lt;br&gt;
• Close tab&lt;br&gt;
• Switch to next tab&lt;br&gt;
• Switch to previous tab&lt;br&gt;
• Go back&lt;br&gt;
• Go forward&lt;br&gt;
• Access URL from navigation bar&lt;br&gt;
• Entering an iframe&lt;br&gt;
• Exiting an iframe&lt;br&gt;
... and many more&lt;/p&gt;

&lt;p&gt;Since we're talking about a Chrome extension, the only way to detect such events is through JavaScript and the &lt;a href="https://developer.chrome.com/extensions"&gt;Chrome API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We used different JavaScript event listeners such as onclick, onchange, onkeyup, onmousemove, etc to figure out what the user does. &lt;/p&gt;

&lt;p&gt;It's important to distinguish between the different actions. &lt;/p&gt;

&lt;p&gt;For example, when a user is typing inside an input, you need to register that as a "Write Text" action. &lt;/p&gt;

&lt;p&gt;But when the user pressed the Enter key or the Escape key, you need to register that as a "Press Key" action.&lt;/p&gt;

&lt;p&gt;The user has the option to enable or disable the detection of Hover and Scroll events, since they're not relevant in all situations. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6tM7lioj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mkv7pmp8q4qzvh9m58xe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6tM7lioj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mkv7pmp8q4qzvh9m58xe.png" alt="Endtest Recorder Settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even if a user enables the detection of Hover events, they will only be logged if the duration of Hover is above a certain number of miliseconds. &lt;/p&gt;

&lt;p&gt;This is done to avoid recording unnecessary Hover events when the user is simply moving the pointer.&lt;/p&gt;

&lt;p&gt;The Chrome API is used to detect actions which cannot be detected with JavaScript, such as when the user is opening a new tab or switching focus to a different tab.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;2. Getting the right permissions&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Being able to record everything that a user does in the browser might sound like a job for the NSA.&lt;/p&gt;

&lt;p&gt;Luckily, Chrome is smart enough to let you declare what permissions you need in the manifest.json file.&lt;/p&gt;

&lt;p&gt;They also review those permissions when you publish the extension in the Chrome Web Store. &lt;/p&gt;

&lt;p&gt;And the user is informed about those permissions when installing the extension.&lt;/p&gt;

&lt;p&gt;Here is what the permissions for our extension like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;permissions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;activeTab&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;all_urls&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cookies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;storage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tabs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;webNavigation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;3. Locating the elements&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It's no secret that our engine for Web Tests is using Selenium.&lt;/p&gt;

&lt;p&gt;That's why we need to fetch locators for the elements that the users interacts with. &lt;/p&gt;

&lt;p&gt;If we would rely on coordinates or image recognition, that would lead to brittle tests.&lt;/p&gt;

&lt;p&gt;We fetch the following locators:&lt;br&gt;
• ID&lt;br&gt;
• Name&lt;br&gt;
• CSS Selector&lt;br&gt;
• XPath&lt;/p&gt;

&lt;p&gt;Fetching the ID for an element might seem as simple as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;the_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But there are plenty of tricky situations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The element does not have an ID&lt;/li&gt;
&lt;li&gt;Multiple elements share the same ID&lt;/li&gt;
&lt;li&gt;The ID is generated dynamically and changes with each refresh&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This means that we always check for uniqueness and we try to detect and avoid using IDs which are dynamic. &lt;/p&gt;

&lt;p&gt;The same rules apply for the Name attribute. &lt;/p&gt;

&lt;p&gt;CSS Selectors can be generated by using the using the attributes from an element and the parent nodes.&lt;/p&gt;

&lt;p&gt;Let's take a look at this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"login-form"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"mat-input-6"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Email"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"mat-input-9"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Password"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can easily spot that the IDs are dynamic, so we have to avoid them.&lt;/p&gt;

&lt;p&gt;The basic CSS Selector for the Email input would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;&lt;span class="nx"&gt;nth&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But we can easily construct something more reliable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Most people ditch XPaths for CSS Selectors, thinking that they're just as powerful, but slower. Big mistake.&lt;/p&gt;

&lt;p&gt;XPaths have some hidden tricks up their sleeves. &lt;/p&gt;

&lt;p&gt;The XPath equivalent to the previous CSS Selector would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xpath"&gt;&lt;code&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;@placeholder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Email"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But here's a situation where XPath can save your life:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"items"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Apple&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Orange&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Banana&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's try to fetch a locator for the Orange list item.&lt;/p&gt;

&lt;p&gt;CSS Selectors do not have the ability to locate an element based on the text, but XPaths do. &lt;/p&gt;

&lt;p&gt;The XPath for the Orange list item is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xpath"&gt;&lt;code&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;'Orange'&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We even offer advanced settings for detecting locators:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OPNEyf-Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rbgoqzwq7c5yvmq0ghz6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OPNEyf-Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rbgoqzwq7c5yvmq0ghz6.png" alt="Endtest Recorder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using classes in CSS Selectors and XPaths can also be tricky, since they can only appear in the element when you click on it. &lt;/p&gt;

&lt;p&gt;Let's take a look at this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"login-form"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We want to locate the input type="button" element. &lt;/p&gt;

&lt;p&gt;But when we click on that input, it gets 2 extra classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"login-form active focus"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since we're recording the event at the moment of the click, our Chrome Extension would record the element as having 2 extra classes.&lt;/p&gt;

&lt;p&gt;If this would happen, our engine would throw an "Element not found" error when the test would be executed, since those 2 extra classes are not appended if the element isn't clicked. &lt;/p&gt;

&lt;p&gt;That's why allow the users to have a list of classes that our Chrome Extension can simply ignore:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kw62hq-q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yp5r7qd97ey8qlul4c05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kw62hq-q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yp5r7qd97ey8qlul4c05.png" alt="Endtest Chrome Extension Classes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Going the extra mile&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We always make sure our users get the best experience.&lt;/p&gt;

&lt;p&gt;Steps for taking screenshots and adding assertions can be added directly from the recorder. &lt;/p&gt;

&lt;p&gt;The recording process can also be paused and resumed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BE7oxqEG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yw4s98e8be0hohdfbzfy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BE7oxqEG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yw4s98e8be0hohdfbzfy.png" alt="Endtest Recorder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find more details in our &lt;a href="https://endtest.io/guides/docs/how-to-create-web-tests/"&gt;Documentation&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Q&amp;amp;A&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. Why do we also offer a cross-browser cloud infrastructure?&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;We take testing very seriously.&lt;/p&gt;

&lt;p&gt;That's why our cloud platform offers real browsers on Windows and macOS machines and mobile devices. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rtQ3k8yV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cx4qm6rde0hduxi5e4vv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rtQ3k8yV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cx4qm6rde0hduxi5e4vv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We encourage developers to avoid using headless browsers on Linux machines for their automated tests, since those browsers do not have the same behavior as the real browsers used by users.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;2. Why record the tests with JavaScript and execute them with Selenium?&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Since our recorder had to be a Chrome extension, we had no other choice than to use JavaScript.&lt;/p&gt;

&lt;p&gt;Our engine for Web Tests is using Selenium, because it's open-source, constantly improved, mimics real user behavior and it works with all the major browsers.&lt;/p&gt;

&lt;p&gt;We advise developers to avoid using JavaScript-based libraries for executing automated tests in the UI, since those libraries have severe limitations and do not mimic real user behavior. &lt;/p&gt;

&lt;p&gt;For example, a JavaScript-based library for testing the UI can easily click on an element which is completely covered by another element. &lt;br&gt;
A real user and a Selenium test cannot do that.&lt;/p&gt;

&lt;p&gt;A JavaScript library for testing the UI cannot perform file uploads, cannot manage iframes and cannot manage multiple browser tabs. &lt;/p&gt;

&lt;p&gt;Currently, there isn't any JavaScript library for UI testing that works on all the major browsers and devices. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>testing</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How Endtest Is Using Machine Learning To Make Your Tests More Stable</title>
      <dc:creator>endtest</dc:creator>
      <pubDate>Mon, 13 May 2019 15:21:22 +0000</pubDate>
      <link>https://dev.to/endtest_io/how-endtest-is-using-machine-learning-to-make-your-tests-more-stable-52hn</link>
      <guid>https://dev.to/endtest_io/how-endtest-is-using-machine-learning-to-make-your-tests-more-stable-52hn</guid>
      <description>&lt;p&gt;It's no secret that we use Machine Learning here at Endtest.&lt;/p&gt;

&lt;p&gt;And it's not just a buzzword that we throw around to attract users. &lt;/p&gt;

&lt;p&gt;In this article, we'll show you how it works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://endtest.io"&gt;Endtest&lt;/a&gt; is a cloud platform where anyone can create, manage and run automated tests for Web and Mobile Apps, without having to write any code. &lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/4DIVKcs--TA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;We're talking about functional tests, which interact with the app in the same way that a user would, through the UI.&lt;/p&gt;

&lt;p&gt;Our engine is using Python and Selenium to interact with the elements from Web Applications and Python and Appium to interact with the elements from Mobile Applications.&lt;/p&gt;

&lt;p&gt;In order to find an element with Selenium and Appium, you need to provide a locator for that element. &lt;/p&gt;

&lt;p&gt;Let's take a look at a quick example.&lt;/p&gt;

&lt;p&gt;The Email address input from the Sign Up form at &lt;a href="https://airbnb.com"&gt;Airbnb&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gBekab-D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/RKz99jt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gBekab-D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/RKz99jt.png" alt="airbnb email input"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When creating a Selenium test, you could use one of the following locators to find that input:&lt;br&gt;
&lt;strong&gt;ID&lt;/strong&gt; = email-signup-email&lt;br&gt;
&lt;strong&gt;Name&lt;/strong&gt; = user[email]&lt;br&gt;
&lt;strong&gt;Class Name&lt;/strong&gt; = _14fdu48d&lt;br&gt;
&lt;strong&gt;XPath&lt;/strong&gt; = //*[&lt;a class="comment-mentioned-user" href="https://dev.to/id"&gt;@id&lt;/a&gt;
="email-signup-email"]&lt;br&gt;
&lt;strong&gt;CSS Selector&lt;/strong&gt; = #email-signup-email&lt;/p&gt;

&lt;p&gt;You could go the extra mile and write your own custom XPaths based on any attributes which uniquely identify that element: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;XPath&lt;/strong&gt; = //*[@type="email"]&lt;br&gt;
&lt;strong&gt;XPath&lt;/strong&gt; = //*[@autocomplete="username"]&lt;br&gt;
&lt;strong&gt;XPath&lt;/strong&gt; = //*[@placeholder="Email address"]&lt;br&gt;
&lt;strong&gt;XPath&lt;/strong&gt; = //*[@type="email" and @autocomplete="username"]&lt;/p&gt;

&lt;p&gt;When you write such a test, you would only use one of those locators. &lt;/p&gt;

&lt;p&gt;Now, I want you to choose the locator which you think is the most reliable.&lt;/p&gt;

&lt;p&gt;Alright, did you pick one? Great, we're going to need it for the next step.&lt;/p&gt;

&lt;p&gt;Let's imagine that Airbnb would go through a revamping.&lt;/p&gt;

&lt;p&gt;And that input would now look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H9zssN4D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/4aeEL8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H9zssN4D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/4aeEL8n.png" alt="airbnb email input"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What locator did you pick? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You picked ID, didn't you?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sadly, your test will now fail and it will give you a false negative.&lt;/p&gt;

&lt;p&gt;Seems you need to update it.&lt;/p&gt;

&lt;p&gt;Someone working on tests always goes through that, the pain of maintenance. &lt;/p&gt;

&lt;p&gt;Updating one step isn't time-consuming, but it's rarely just one.&lt;/p&gt;

&lt;p&gt;That's one of the many problems that we're solving with our platform. &lt;/p&gt;

&lt;p&gt;Just enable the Machine Learning option from the Advanced Settings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u2dAzBTR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/nKv3T4S.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u2dAzBTR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/nKv3T4S.png" alt="endtest advanced settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And when you run your test, our engine will remember between 50 and 100 ways to locate your element. &lt;/p&gt;

&lt;p&gt;It will remember all the attributes, XPaths and CSS Selectors. details about the neighbours and the element's role in the workflow. &lt;/p&gt;

&lt;p&gt;All that information will be useful when changes in your application will occur.&lt;/p&gt;

&lt;p&gt;If those changes break your tests, our engine can easily update your tests to match the latest changes. &lt;/p&gt;

&lt;p&gt;All you have to do is enable the Self-Healing option when you run your test:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mUSbhbEi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/StEIoZz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mUSbhbEi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/StEIoZz.png" alt="endtest self-healing tests"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When that test will reach a step that no longer corresponds to the new UI and workflow, it will fetch all the information that it gathered about the element, it will scrape the page in multiple threads, it will perform a ton of calculations and rankings to determine if the element is still on that page and determine what are the new locators.&lt;/p&gt;

&lt;p&gt;It will update your test in order to match the latest changes from your app.&lt;/p&gt;

&lt;p&gt;From our thorough experiments, we got an accuracy of 98%.&lt;/p&gt;

&lt;p&gt;Our algorithms can actually differentiate an intended change from a bug. &lt;/p&gt;

&lt;p&gt;Each step that was updated by our engine will be detailed in the Results section.&lt;/p&gt;

&lt;p&gt;In the Machine Learning world, this is known as &lt;strong&gt;Supervised Learning&lt;/strong&gt;. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>testing</category>
      <category>devops</category>
    </item>
    <item>
      <title>10 Unexpected Ways To Improve Your Automated Tests</title>
      <dc:creator>endtest</dc:creator>
      <pubDate>Wed, 18 Jul 2018 11:59:21 +0000</pubDate>
      <link>https://dev.to/endtest_io/10-unexpected-ways-to-improve-your-automated-tests-4i4a</link>
      <guid>https://dev.to/endtest_io/10-unexpected-ways-to-improve-your-automated-tests-4i4a</guid>
      <description>&lt;p&gt;&lt;strong&gt;Should I use Selenium&lt;/strong&gt; or something else? &lt;strong&gt;Should I make&lt;/strong&gt; a list of everything that needs to be automated? &lt;strong&gt;Should I ask&lt;/strong&gt; for help?&lt;/p&gt;

&lt;p&gt;Sounds familiar?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I know the feeling. I felt the same way.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whether you are a &lt;strong&gt;beginner&lt;/strong&gt; or an &lt;strong&gt;expert&lt;/strong&gt;, chances are some of these points will help you &lt;strong&gt;bring your automated testing skills to the next level&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here are 10 unexpected ways to help you &lt;strong&gt;improve your automated tests&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Embrace the ever-changing technology trends&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Coding your own automated testing framework can make your life a living hell. So, how about you avoid perdition and accept innovation?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OaxNDoMG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/GC2F8qx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OaxNDoMG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/GC2F8qx.jpg" alt="bad code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The worst part is that you're not going to realize that…at least until it's too late.&lt;/p&gt;

&lt;p&gt;Creating a basic test suite is a piece of cake, but would you enjoy maintaining the entire codebase when 478 out of your 626 tests will be failing due to different errors, right before the big release?&lt;/p&gt;

&lt;p&gt;…&lt;/p&gt;

&lt;p&gt;That's right. &lt;/p&gt;

&lt;p&gt;Yep, your entire team will end up doing manual testing for the next couple of days. Bummer, huh?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--idG6aNjb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/ZzRBhoF.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--idG6aNjb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/ZzRBhoF.jpg" alt="robot maintenance automated testing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're thinking "That's totally not me", ask yourself if you have the time to handle:&lt;br&gt;
• Creating a stable cross-browser cloud infrastructure for your tests.&lt;br&gt;
• Implementing image comparison algorithms for visual checks.&lt;br&gt;
• Implementing video recording for your test runs.&lt;br&gt;
• Implementing a schedule for your tests to run on a daily basis.&lt;br&gt;
• Integrating your tests with your CI/CD system.&lt;/p&gt;

&lt;p&gt;If the answer is &lt;strong&gt;"yes"&lt;/strong&gt;, you can stop reading from here on.&lt;/p&gt;

&lt;p&gt;If the answer is &lt;strong&gt;"no"&lt;/strong&gt;, the next question should be &lt;strong&gt;"alright, what's the alternative?"&lt;/strong&gt;. &lt;br&gt;
Good news is that companies have started migrating to cloud platforms that provide testing infrastructure (IaaS, PaaS and SaaS).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MkWmGRCv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/C4tavcC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MkWmGRCv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/C4tavcC.png" alt="software testing tools"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's what I could find about them, after doing some extensive research:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZbK0OS11--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/W9bQPtk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZbK0OS11--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/W9bQPtk.png" alt="software testing tools comparison"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As for Cucumber or Behat, they are just libraries so I couldn't find a spot for them here.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Make stability a priority.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If your test passed 99 times and failed once, the bottom line is that your automated tests are &lt;strong&gt;unstable&lt;/strong&gt;, as unpleasant as acknowledging that may be.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2V5SgSId--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/dEsdCE1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2V5SgSId--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/dEsdCE1.png" alt="developer life"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Having 2 stable tests instead of 5 unstable ones is always better. Those unstable tests will just test your patience and force you to manually check the functionality over and over again.&lt;/p&gt;

&lt;p&gt;You already know that it's not a smart move to move on to the next test case until the one you're working on is completely stable.&lt;/p&gt;

&lt;p&gt;That sneaky &lt;strong&gt;"I'm going to come back and fix it anyway"&lt;/strong&gt; lingering in your mind won't happen and you're just going to end up doing extra work to fix it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FC8Qe5AH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/usmrd6F.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FC8Qe5AH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/usmrd6F.jpg" alt="big bug"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. It's OKAY to be OBSESSED.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Don't forget to focus on the negative testing scenarios, that's where the bugs crawl, they don't like the clean happy path.&lt;/p&gt;

&lt;p&gt;Create a test for each bug you find while manually testing, so you know it will never cheap-shot you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8pDJVihz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/Hr9XiCV.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8pDJVihz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/Hr9XiCV.jpg" alt="bugs after release"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Visuals are important.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Even if your tests are interacting with the applications via the UI and you're checking for the existence of some elements, that doesn't mean everything will be pixel perfect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RE92oMxa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/Ldrta0j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RE92oMxa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/Ldrta0j.jpg" alt="visual testing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's why it's important to add screenshot comparison steps that visually check elements, pixel by pixel, against already existing screenshots.&lt;/p&gt;

&lt;p&gt;I wrote a short technical &lt;a href="https://medium.com/@liviu.lupei/screenshot-comparison-for-selenium-tests-84f1badda532"&gt;article&lt;/a&gt;  - - that you might find useful  --  about doing that, a few months ago.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. You. Can't. Automate. Everything.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Sadly, there are some things that can't be automated in a stable and efficient manner. The sooner we accept that, the better.&lt;br&gt;
Take &lt;strong&gt;reCAPTCHA&lt;/strong&gt; for example, you're probably going to find yourself in need to disable it for the requests coming from your test machines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qUEQg7LR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/ihBnVUX.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qUEQg7LR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/ihBnVUX.jpg" alt="captcha"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dwelling on automating the impossible will just waste your time.&lt;br&gt;
Luckily, there are smart workarounds out there. All you have to do is find them.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;6. Cross Browser: You DO need it.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;"Well, our web application is working great in Chrome…"&lt;br&gt;
"And that's what most people are using anyway…"&lt;br&gt;
"Hmm, it would take us some time to make the tests run on all the browsers…"&lt;br&gt;
"Some users have been reporting some bugs, maybe they're using some old version of Chrome or … you know, users are just stupid sometimes."&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Curiosity drives you to go around and ask for statistics about what browsers people are using to access your web application.&lt;/p&gt;

&lt;p&gt;That's how you get this lovely pie chart:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DnG_BPPu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/Z2zoGYK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DnG_BPPu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/Z2zoGYK.png" alt="browser pie chart"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How f****d are you?&lt;/p&gt;

&lt;p&gt;This is when you know you need to go Cross Browser, there is really no other way to go.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KPigkZ7J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/GXRRNXS.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KPigkZ7J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/GXRRNXS.jpg" alt="browser wars"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It may be complicated and, sometimes, expensive, but it's always worth it.&lt;/p&gt;

&lt;p&gt;And if you're going to go, go all the way:&lt;br&gt;
• Don't rely on headless browsers.&lt;br&gt;
• Use Windows machines for testing in Chrome, Firefox and IE.&lt;br&gt;
• Use Windows 10 machines for testing in Edge.&lt;br&gt;
• Use Mac OS machines for testing in Safari, Chrome and Firefox.&lt;/p&gt;

&lt;p&gt;If you're going to go codeless, the only platform that offers the above - while being…well, codeless  -  at the moment, is &lt;a href="https://endtest.io"&gt;Endtest&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;7. Remember the little things.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Sometimes, I tend to forget those little things that do matter.&lt;br&gt;
Here are some questions to ask yourself when you think you're done:&lt;/p&gt;

&lt;p&gt;• When was the last time you tested the META tags from the Page Source?&lt;br&gt;
• When was the last time you tested the cookies?&lt;/p&gt;

&lt;p&gt;These things are surprisingly important for ranking, marketing and tracking purposes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o1UmTP44--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/8gqn9fj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o1UmTP44--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/8gqn9fj.jpg" alt="web visitor tracking"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;8. Sometimes, Mobile comes First.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Those who are working on B2C products already know that most users access their product through their mobile device. &lt;br&gt;
Those who are working on B2B products need to start considering the same thing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--whHVHx1D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/42klXPw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--whHVHx1D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/42klXPw.jpg" alt="mobile testing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;9. Not just the testers, but everyone should write tests.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Since the Product Owner and the Business Analyst are the ones who know best how the software and flows &lt;strong&gt;should&lt;/strong&gt; work, they're the best people to take part in the quest that test-writing can be.&lt;/p&gt;

&lt;p&gt;Their take will always be useful when writing the tests for happy paths.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S7YGwD_L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/WWwmAAW.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S7YGwD_L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/WWwmAAW.jpg" alt="product owner"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This experience is a win-win, since it also helps them gain a little more insight on how their User Stories were implemented.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;But they might not know how to write code….&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For this kind of scenario, going &lt;a href="https://endtest.io"&gt;codeless&lt;/a&gt; is the only way to go if you're not willing to spend months on teaching them how to do it. If you are, I must say I admire your patience.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;10. Don't be afraid to ask for a little bit of help.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Since the entire company will benefit from those automated tests, everyone will gladly pitch in if you need a little hand ( even if you know &lt;strong&gt;better&lt;/strong&gt;! ).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xv4sA-uP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/4GUSKQR.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xv4sA-uP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/4GUSKQR.jpg" alt="peer programming"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>devops</category>
      <category>javascript</category>
      <category>android</category>
    </item>
  </channel>
</rss>
