<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Alex Sim on Medium]]></title>
        <description><![CDATA[Stories by Alex Sim on Medium]]></description>
        <link>https://medium.com/@alexsiminiuc3?source=rss-7d1d957797d3------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*n_rhNEOTQEG18aSP.</url>
            <title>Stories by Alex Sim on Medium</title>
            <link>https://medium.com/@alexsiminiuc3?source=rss-7d1d957797d3------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 07:07:20 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@alexsiminiuc3/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Dont Use Object Repositories with Selenium WebDriver]]></title>
            <link>https://medium.com/@alexsiminiuc3/dont-use-object-repositories-with-selenium-webdriver-ad14096528e5?source=rss-7d1d957797d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/ad14096528e5</guid>
            <category><![CDATA[testing]]></category>
            <category><![CDATA[software-testing]]></category>
            <category><![CDATA[selenium]]></category>
            <category><![CDATA[selenium-test-automation]]></category>
            <category><![CDATA[selenium-webdriver]]></category>
            <dc:creator><![CDATA[Alex Sim]]></dc:creator>
            <pubDate>Sun, 26 Nov 2017 20:58:47 GMT</pubDate>
            <atom:updated>2017-11-26T23:28:54.898Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/560/1*l2LxmZo0tNof1amRRfmX_g.png" /></figure><p>Selenium WebDriver is rather new in the test automation world.</p><p>Before Selenium, all attention and spotlight belonged to a product called QTP (UFT is the new name), built by Mercury Interactive (owned now by HP).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/583/1*PyCL4L1BrAtZw11PrGroYw.jpeg" /></figure><p>Everyone was talking about QTP and <a href="https://en.wikipedia.org/wiki/Mercury_(element)">Mercury</a> so much that the Selenium creator, Jason Huggings, named his new automation tool after another chemical element, <a href="https://en.wikipedia.org/wiki/Selenium">Selenium</a>.</p><h3>How does QTP work?</h3><p>QTP allows automation tests to be created for a variety of application types in 2 different ways:</p><ol><li>through <strong>record-and-play</strong></li><li>through <strong>code</strong></li></ol><p>When using the record-and-play mode, the user goes through the following steps to record a new test:</p><ol><li>opens the QTP application</li><li>selects the record button</li><li>selects the application to be tested</li><li>starts the recording</li><li>goes through the application like a normal user</li><li>stops the recording</li></ol><p>After the recording is stopped, a new automated test is created.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*b5r0N34XkVCrs6DGf0RBXg.jpeg" /></figure><p>The automated test can be played back.</p><p>Its code uses items from an object repository that is created during the recording process:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*0fiWlvpFj9n2AB9CMo0DKQ.jpeg" /></figure><p><strong>The object repository is a tree-like structure that has a node for each application element used during recording.</strong></p><p>Each node has in the object repository multiple attributes:</p><ol><li>name</li><li>class</li><li>type</li><li>locator</li><li>value</li></ol><p>So the automation code works by interacting with application elements found in the object repository.</p><h3>This seems a decent approach. Why not use it with Selenium WebDriver as well?</h3><p>Test automation with Selenium WebDriver is done 100% through code.</p><p>There is a tool called Selenium IDE that relies on record-and-play but it is useless for serious test automation due to numerous limitations.</p><p><strong>Test automation with Selenium WebDriver does not rely at all on record-and-play.</strong></p><p>And object repository is a record-and-play concept.</p><p>Without recording the test, how would the object repository be created?</p><p><strong>Does this mean though that the object repository cannot be used with Selenium automation?</strong></p><p>Lets see how code looks when using an object repository.</p><p>We have a Home Page class that implements the user interaction with a typical Home Page such as the Hudson Bay’s one</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PdzN78SPSJVjwu8eAitPyA.png" /></figure><p>The object repository for the page could be a property file (or xml, csv, yaml) as follows:</p><pre>BRANDS = brands.id</pre><pre>WOMEN = women.id</pre><pre>SHOES = shoes.id</pre><pre>HANDBAGS = handbags.id</pre><pre>ACCESSORIES = accessories.id</pre><pre>BLACK_FRIDAY_SALE = blackfridaysale.id</pre><pre>BLACK_FRIDAY_DEAL = blackfridaydeal.id</pre><p>The HomePage.java page object class uses the element ids from the object repository:</p><pre><strong><br>public</strong> <strong>class</strong> HomePage {</pre><pre><strong>  private</strong> WebDriver <em>driver</em>;</pre><pre><strong>  private</strong> PropertyFile <em>props</em>;</pre><pre><strong>  private</strong> <strong>final</strong> String <em>URL</em> = “<a href="http://www.vpl.ca/">http://www.thebay.com</a>&quot;;</pre><pre><strong>  public</strong> HomePage (WebDriver <em>driver</em>) {</pre><pre><strong>     this</strong>.<em>driver</em> = <em>driver</em>;</pre><pre><strong>     this</strong>.<em>props</em> = <strong>new</strong> PropertyFile(“homePage.properties”);</pre><pre>  }</pre><pre><strong>  public</strong> <strong>void</strong> open() {</pre><pre><em>    driver</em>.get(<em>URL</em>);</pre><pre>  }</pre><pre><strong>  public</strong> BrandsPage<strong> </strong>goToBrands() {</pre><pre>   By brands<em>Id</em> = By.id(props.(“BRANDS”));</pre><pre>   WebElement brands= <em>driver</em>.findElement(brands<em>Id</em>);</pre><pre><em>   brands</em>.click();   </pre><pre>   return new BrandsPage(this.driver);   </pre><pre>  }</pre><pre><strong>   public</strong> WomenApparelPage<strong> </strong>goToWomenApparel() {</pre><pre>     By women<em>Id</em> = By.id(props.get(“WOMEN”));</pre><pre>     WebElement women= <em>driver</em>.findElement(women<em>Id</em>);</pre><pre><em>     women</em>.click();</pre><pre>     return new WomenApparelPage(this.driver);</pre><pre>  }</pre><pre>  .......................</pre><pre>}</pre><p>I added only 2 methods to the class for the first 2 top menu options, Brands and Women.</p><p>Each method gets the menu option’s locator through an object of the PropertyFile class.</p><p>This class opens the property file, searches for a property name, gets the property value and returns it:</p><pre>package Property;</pre><pre>import java.io.File;<br>import java.io.FileInputStream;<br>import java.io.InputStream;<br>import java.util.Properties;</pre><pre>public class PropertyFile {<br> <br> private final Properties properties;<br> <br> public PropertyFile(String fileName)<br> {  <br>  try {   <br>     properties = new Properties();   <br>     File file = new File(fileName);<br>     InputStream input = new FileInputStream(file); <br>     properties.load(input);   <br>  }<br>  catch (Exception exception) {<br>     throw new RuntimeException (&quot;cannot load the property file&quot;);<br>  }  <br> }<br> <br> public String get(String name)  {  <br>  try {<br>   return properties.getProperty(name);<br>  }<br>  catch(Exception exception) {<br>   throw new RuntimeException (&quot;cannot find &quot;+ name);<br>  }   <br> }<br>}</pre><h3>What are the “advantages” of using an object repository?</h3><ol><li>All locators for the elements of a page are in 1 place</li><li>Since the page classes dont have locator variables, they are shorter.</li></ol><p>You noticed, of course, that there are double quotes around advantages.</p><p>They are actually disadvantages.</p><h3>What are the disadvantages of an object repository?</h3><ol><li><strong>It is very difficult to read or change the value of an element locator</strong></li></ol><p>An ecommerce site has more than 50 pages, each with hundreds of elements.</p><p>We will have then an object repository for each page.</p><p>While working with code, there are many times when we need to either read or change the value of a locator.</p><p>Usually, this is done in the IDE (Eclipse, Intellij) by pressing the F3 key or selecting Open Declaration for the locator variable:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/378/1*iogeUm-EkzUV13L92-F4xg.png" /></figure><p>This does not work with object repositories since a locator is just a line in a text file.</p><p>To read or change the locator value, you have to</p><ul><li>find the object repository for the page</li><li>open it</li><li>search for the element name in the file</li></ul><p>That’s a lot of work for just reading a locator value.</p><p>2. <strong>A page object class becomes a method container if it has no locator variables.</strong></p><p>Page object classes are classes.</p><p>A JAVA class has variables for state and methods for behavior.</p><p>The methods operate on the variables of the class:</p><blockquote>Encapsulation (computer programming)</blockquote><blockquote><a href="https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)">From Wikipedia, the free encyclopedia</a></blockquote><blockquote>In programming languages, <strong>encapsulation</strong> is used to refer to one of two related but distinct notions, and sometimes to the combination thereof:</blockquote><blockquote>- A language mechanism for restricting direct access to some of the object’s components.</blockquote><blockquote>- <strong>A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data</strong>.</blockquote><p>Removing the locator variables from a page object class means violating the encapsulation principle since</p><ul><li>the class does not have variables any longer</li><li>its methods do not operate on the class variables</li></ul><p><strong>3. Using object repositories does not scale well for big page object classes</strong></p><p>The HomePage class for the HudsonBay site will be big, with lots of locators and lots of methods.</p><p>Having big classes with more than 200 lines of code and more than 10 methods is a bad practice.</p><p>So they should be broken down in smaller classes.</p><p>We could do this for the HomePage by creating classes for the HomePage widgets:</p><ul><li>top menu widget</li><li>sales and deals widget</li><li>header (sign in, my account, gift cards, gift registry, etc)</li><li>search</li><li>best sellers</li><li>black friday deals</li><li>sponsored products</li><li>footer</li></ul><p>Using page element classes for all widgets will simplify the Home Page class significantly and allow us to keep it small.</p><p>But how do we do this with object repositories?</p><p>Use the HomePage repository for all page element classes?</p><p>Or create an object repository for each page widget?</p><p><strong>4. Object repositories do not work well with the Page Factory pattern</strong></p><p>This should be no surprise since Page Factory declares together web elements and their locators:</p><pre><strong>public</strong> <strong>class</strong> HomePage {</pre><pre><strong>private</strong> WebDriver <em>driver</em>;</pre><pre><strong>private</strong> <strong>final</strong> String <em>URL</em> = “<a href="http://www.vpl.ca/">http://www.thebay.com</a>&quot;;<br></pre><pre><strong>@FindBy</strong>(how = How.ID, using = &quot;brands.id&quot;)</pre><pre><strong>private</strong> WebElement brands;</pre><pre><strong>@FindBy</strong>(how = How.ID, using = &quot;women.id&quot;)</pre><pre><strong>private</strong> WebElement women;<br></pre><pre><strong>public</strong> HomePage (WebDriver <em>driver</em>) {</pre><pre><strong>  this</strong>.<em>driver</em> = <em>driver</em>;</pre><pre>}</pre><pre><strong>public</strong> <strong>void</strong> open() {</pre><pre><em>  driver</em>.get(<em>URL</em>);</pre><pre>}</pre><pre><strong>public</strong> BrandsPage<strong> </strong>goToBrands() {</pre><pre><em>   brands</em>.click();</pre><pre>   return new BrandsPage(this.driver);</pre><pre>}</pre><pre><strong>public</strong> WomenApparelPage<strong> </strong>goToWomenApparel() {</pre><pre><em>  women</em>.click();</pre><pre>  return new WomenApparelPage(this.driver);</pre><pre>}</pre><pre>.......................</pre><pre>}</pre><h3>Why are people still suggesting using object repositories with Selenium WebDriver?</h3><p>One reason may be that many testers learned Selenium WebDriver after working with QTP for a long time.</p><p>How QTP works became so familiar to them that they use QTP concepts everywhere.</p><p>Another reason may be that it is far easier to write procedural code (as in VB, VB SCRIPT) than object oriented code (as in JAVA or C#).</p><p>This article is inspired from a chapter of my new book on improving Selenium code with page object models.</p><p>You can find it on Amazon . com at</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/217/1*2uOkqGo1OWv3qBFd-UMTEA.jpeg" /></figure><p><a href="https://www.amazon.com/Improve-Selenium-Code-Automation-Patterns-ebook/dp/B077QFN53F/ref=sr_1_8?ie=UTF8&amp;qid=1511652213&amp;sr=8-8&amp;keywords=page+object+model">Improve Selenium Code with Automation Patterns: Page Object Model Page Factory Page Elements Base Page Loadable Component</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ad14096528e5" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Bad coding practices for test automation with Selenium WebDriver]]></title>
            <link>https://medium.com/@alexsiminiuc3/bad-coding-practices-for-test-automation-with-selenium-webdriver-4dba947ceed0?source=rss-7d1d957797d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/4dba947ceed0</guid>
            <category><![CDATA[selenium-test-automation]]></category>
            <category><![CDATA[selenium]]></category>
            <category><![CDATA[selenium-webdriver]]></category>
            <category><![CDATA[test-automation]]></category>
            <dc:creator><![CDATA[Alex Sim]]></dc:creator>
            <pubDate>Sat, 28 Oct 2017 23:24:47 GMT</pubDate>
            <atom:updated>2017-10-28T23:34:37.618Z</atom:updated>
            <content:encoded><![CDATA[<p>Everybody tells you what to do for Selenium test automation and how to do it.</p><p>How to create the driver object.</p><p>How to find elements.</p><p>How to switch to a frame.</p><p>How to create a page object.</p><p>I will do the opposite.</p><p><strong>It is as useful, maybe even more, to see what you should not do.</strong></p><p>One may think that, with such a great amount of available advice in blogs, courses and books, most test automation code is good or at least decent.</p><p>In reality, in most cases that I was exposed to, it is really bad.</p><p>The bad automation code may come from offshore automation “experts” or from local automation “consultants”.</p><p>No difference.</p><p>Every time I see samples of it, “what the fuck!” is the first reaction.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*5RhyUqWmrXugwrjchoA5rA.jpeg" /></figure><p>Source: <a href="https://www.osnews.com/story/19266/WTFs_m">https://www.osnews.com/story/19266/WTFs_m</a></p><p>I still remember how I reacted seeing this cartoon: laughing until I could not breathe any more.</p><p>These days, I am not laughing at all.</p><p>Because <strong>test automation becomes the place inhabited by </strong>either</p><p>- <strong>unprofessional developers</strong>, who failed at development</p><p>or</p><p>- <strong>manual testers converted to junior developers</strong>, who failed at manual testing</p><p>Some of these people have certifications as well to prove their lack of skills and knowledge:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/550/1*r1K5fFM1EWYoZh2-RmuHWw.jpeg" /></figure><p>I should probably be happy that so many people write awful code since there are more opportunities available.</p><p>I am frustrated instead.</p><p>Because that’s what is going on with manual testing as well.</p><p>There have been so many unprofessional manual testers out there and for such a long time that manual testing is slowly going away.</p><p>I will not be surprised if the same happens to test automation, change into application UI automation and be a development activity.</p><p>Who needs junior automation developers?<br>Or fake automation engineers?</p><p>What follows are code samples from “test automation experts”.</p><p>I did not make them up.</p><p>They are all real.</p><blockquote>Wait For Page To Load</blockquote><pre>public void waitForPageToLoad(String string){<br>  String url = browserDriver.getCurrentUrl();<br>  Boolean stringExists = url.contains(string);<br>  int Count = 0;<br> <br>  while (Boolean.FALSE.equals(stringExists) &amp;&amp; Count &lt; 100){<br>     url = browserDriver.getCurrentUrl();<br>     stringExists = url.contains(string);<br>     Count = Count + 1;<br>     try {<br>        Thread.sleep(500);<br>     } catch (InterruptedException e) {<br>         // TODO Auto-generated catch block<br>         e.printStackTrace();<br>     }<br>  }<br> <br>   //if(stringExists==false)<br>   if(Boolean.FALSE.equals(stringExists))<br>      throw new IllegalStateException(<br>        “Page not loaded. Current page” + “is: “<br>         + browserDriver.getCurrentUrl()); <br>   }<br>}</pre><p><strong>What’s wrong with this?</strong></p><ol><li>the method name is misleading; the method waits for the url to include a keyword and not for the page to load; a better name is isUrlCorrect()</li><li>do while() would work better than while</li><li>Boolean.FALSE.equals(stringExists) is the same with stringExists == false or !stringExists</li><li>the try/catch for waiting can be extracted in a method</li><li>the code for checking if the url contains a keyword can be extracted in a method</li><li>the exception does not say which page is not loaded</li><li>the parameter should be named keyword instead of string</li><li>Count should be count</li><li>Comments all over the place; not even // TODO Auto-generated catch block is removed</li></ol><p><strong>Can it be done better?</strong></p><pre>public void isUrlCorrect(String keyword){ <br>  int count = 0;<br> <br>   do { <br>     count ++;<br>     waitFor(1);<br>   } while (urlContains(keyword) == false &amp;&amp; count &lt; 30);<br> <br>   if(count == 30)<br>     throw new PageNotDisplayedException(“Page not loaded”);; <br>}</pre><pre>private void urlContains(String keyword) {<br>   return driver.getCurrentUrl().contains(keyword);<br>}</pre><p><strong>Is this the correct way?</strong></p><p>This is a case of <strong>reinventing the wheel</strong>.</p><p>The Selenium WebDriver library has explicit waits and expected conditions for checking if the url is correct:</p><pre>WebDriverWait wait = new WebDriverWait(driver, 30);<br>wait.until(ExpectedConditions.urlContains(keyword));</pre><blockquote>Static Waits</blockquote><pre>public static void Wait(){<br>  try {<br>    Thread.sleep(2000);<br>  } catch (InterruptedException e) {<br>    // TODO Auto-generated catch block<br>    e.printStackTrace();<br>  }<br>}<br> <br>public static void WaitMilliSeconds(int time){<br>  try {<br>    Thread.sleep(time);<br>  } catch (InterruptedException e) {<br>    // TODO Auto-generated catch block<br>    e.printStackTrace();<br>  }<br>}</pre><p><strong>What’s wrong with this?</strong></p><p>The methods have duplicated code.</p><p><strong>Can it be done better?</strong></p><pre>public static void wait(){<br>   wait(2000);<br>}<br> <br>public static void wait(int time){<br>  try {<br>    Thread.sleep(time);<br>  } catch (InterruptedException e) { <br>  }<br>}</pre><p>Isnt this simpler?</p><p>Yes, it is called method overloading.</p><blockquote>Date methods</blockquote><pre>public static String getDateString(int d) {<br>   DateFormat dateFormat = new SimpleDateFormat(“M/d/yyyy”);<br>   Calendar cal = Calendar.getInstance();<br>   cal.add(Calendar.DATE, d); <br>   return dateFormat.format(cal.getTime());<br>}</pre><p><strong>Whats wrong with this?</strong></p><p>Java 8 has the best date and time classes ever called LocalDate and LocalTime.</p><p>Why use date classes from older Java versions if they have much better replacements?</p><p><strong>And now the main attractions….</strong></p><blockquote>Click elements</blockquote><pre>public void Click(){<br>  <br>  driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);</pre><pre>  try {<br>    wait.until(ExpectedConditions.elementToBeClickable(locator));<br>    driver.findElement(locator).click();<br>    System.out.println(“Clicked webelement at: “+locator );<br>  }<br>  catch (RuntimeException e) {<br>    System.out.println(e);<br>    WaitMilliSeconds(500);<br>    if (Boolean.FALSE.equals(<br>                    driver.findElement(locator).isEnabled()))<br>       throw new NoSuchElementException(<br>          “Elment not found at locator: “+ locator);</pre><pre>    driver.findElement(locator).click(); <br> }<br> <br>} </pre><p><strong>What’s wrong with this?</strong></p><ol><li>Click() should be click()</li><li>implicit and explicit waits are used together; this is a bad practice as it leads to unpredictable behaviours</li><li>information is displayed in the console; how is this useful for big tests running in parallel? if you have to log exceptions, at least log them in a file</li><li>an explicit wait waits until the element is displayed and clickable; then, the element is found again and is clicked; why should the element be found twice?</li><li>if there is an exception, if the element is not enabled, an exception is thrown; if the exception is caused by the element not being clickable, the code from the catch() clause is useless<br> <br><strong>What the fuck??????</strong></li></ol><p><strong>Can it be done better?</strong></p><pre>public void click(){ <br> WebElement element = this.wait.until(ExpectedConditions.<br>                            elementToBeClickable(this.locator));<br> element.click();<br>}</pre><p>If the element cannot be found or cannot be clicked, use a different way of finding and clicking it like Javascript.</p><blockquote>SendKeys()</blockquote><pre>public void SendKeys(String text){<br> wait = (new WebDriverWait(driver, 4));<br> try<br> {<br>    wait.until(ExpectedConditions<br>        .visibilityOfElementLocated(locator));<br>    driver.findElement(locator).sendKeys(text);<br>    System.out.println(“Entered sendKey text: “+text);<br>    //SendKeyEnter();<br>    System.out.println(“Click Enter”);<br>    WaitMilliSeconds(1000);<br> }<br> catch(RuntimeException e)<br> {<br>    System.out.println(“\nSecond attempt to SendKey text:” + text);<br>    Wait();<br>    driver.findElement(locator).sendKeys(text);<br>    SendKeyEnter();<br> }<br> <br>}</pre><p><strong>What’s wrong with this?</strong></p><ol><li>SendKeys() should be sendKeys()</li><li>information is displayed in the console</li><li>an explicit wait waits until the element is displayed; visibilityOfElementLocated is used instead of elementToBeClickable;then, the element is found again and text is typed into it; why should the element be found twice?</li><li>if there is an exception, the element is found again and the text typed in it; then, enter is pressed; if the exception is caused because the element is not clickable (because, for example, it is not in the viewport), the code from the catch() clause is useless</li></ol><p><strong>Can it be done better?</strong></p><pre>public void sendKeys(String text){<br>  WebElement element = wait.until(ExpectedConditions<br>                          .visibilityOfElementLocated(locator));<br>  element.sendKeys(text);<br>}<br></pre><blockquote>Wait Until Web Element Clickable</blockquote><pre>public void WaitUntilWebElementClickable(){<br> try {<br>   wait.until(ExpectedConditions.elementToBeClickable(locator));<br> }<br> catch (RuntimeException e) {<br>   WaitMilliSeconds(2000);<br>   driver.navigate().refresh();<br>   System.out.println(“refresh internally…”);<br>   wait.until(ExpectedConditions.elementToBeClickable(<br>        driver.findElement(locator))); <br> }<br>}</pre><p><strong>What’s wrong with this?</strong></p><p>If there is an exception, wait for 2 seconds, then reload the page and try again.</p><p>If the element is not clickable, this may be because <br>1. it is disabled</p><p>2. it is not clickable<br> <br>3. it is not in the view port<br> <br> 4. it is not displayed<br> <br> Reloading the page does not fix any of these problems.</p><p><strong>Can it be done better?</strong></p><pre>public void waitUntilElementClickable(){<br> wait.until(ExpectedConditions.elementToBeClickable(locator)); <br>}</pre><blockquote>getText</blockquote><pre> <br>public String getText() {<br> try {<br>   wait.until(ExpectedConditions<br>          .visibilityOfElementLocated(locator));<br>   return driver.findElement(locator).getText().toString().trim();<br> }<br> catch (RuntimeException e){<br>   System.out.println(“getText() exception: “+ e); <br>   return “”;<br> }<br>}</pre><p><strong>What’s wrong with this?</strong></p><ol><li>getText().toString() is useless since the getText() returns a string</li><li>If there is an exception, the method returns an empty string.<br> <br>If the element does not have a value, the method returns an empty string.<br> <br>So, what does an empty string mean? No element value or an exception happened?</li></ol><p><strong>Can it be done better?</strong></p><pre>public String getText() {<br> WebElement element = wait.until(ExpectedConditions.<br>                         visibilityOfElementLocated(locator));<br> return element.getText().trim(); <br>}</pre><blockquote>refreshPageifNotClickable</blockquote><pre>public void refreshPageifNotClickable()<br> {<br>  try {<br>    wait.until(ExpectedConditions.elementToBeClickable(locator));<br>    System.out.println(“\n “+locator+” is clickable”);<br>  }<br>  catch (RuntimeException e){<br>    driver.navigate().refresh();<br>    BaseHelper.WaitMilliSeconds(2000);<br>    WebElement we = driver.findElement(locator);<br>    wait.until(ExpectedConditions.elementToBeClickable(we));<br>  }<br> }<br> </pre><p><strong>Whats wrong with this?</strong></p><p>Whats the purpose of the method?</p><p>To check if the element is clickable or to refresh the page?</p><p><strong>Can it be done better?</strong></p><p>Yes, by separating it in 2 methods, one for reloading the page, the other for checking if the element is clickable.<br> <br> Is this useful? No.</p><p>I could continue over and over and over with these code samples.</p><p>Each is worse than the previous one.</p><p><strong>One thing that is easy to observe is how non-object-oriented this code is.</strong></p><p>Why non object oriented?</p><p><strong>Because junior developers believe that, for test automation, there is no need to do development like a real developer.</strong></p><p>Concepts like inheritance, composition, interfaces, polymorphism, refactoring, clean design are all unnecessary.</p><p>This is test automation and test goes first.</p><p><strong>It is not called development automation so we can still be testers at it.</strong></p><p>Code that works is sufficient.</p><p>So what companies get VB-written-in-Java or COBOL-written-in-C#.</p><p>As a summary, I want to say just one more thing.</p><p><strong>You need to do development like a developer for good test automation.</strong></p><p>You cannot do it yet?</p><p>Keep learning until you can.</p><p>Or please go back to where you came from, be it manual testing or something else.</p><p>Test automation does not need junior developers, only senior ones.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4dba947ceed0" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>