<?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: Md Zinnun Uddin</title>
    <description>The latest articles on DEV Community by Md Zinnun Uddin (@zinnun).</description>
    <link>https://dev.to/zinnun</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%2F721471%2F8c4969ff-7fa6-4cf2-abbd-39b36fdabce0.png</url>
      <title>DEV Community: Md Zinnun Uddin</title>
      <link>https://dev.to/zinnun</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zinnun"/>
    <language>en</language>
    <item>
      <title>Getting Started with Selenium Grid</title>
      <dc:creator>Md Zinnun Uddin</dc:creator>
      <pubDate>Wed, 24 Aug 2022 04:46:00 +0000</pubDate>
      <link>https://dev.to/zinnun/setting-up-selenium-grid-32dj</link>
      <guid>https://dev.to/zinnun/setting-up-selenium-grid-32dj</guid>
      <description>&lt;p&gt;I was learning docker to containerize automation testcases. Moving forward, I realized- I don't even have the basics and it is difficult to setup and run testcases without knowing the fundamentals of &lt;strong&gt;&lt;em&gt;Selenium Grid&lt;/em&gt;&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;So, I decided to start learning grid first, then coming back to docker. Reading this blog you will know about grid from very basic to some basics 😄&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 01: Configure
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Assuming&lt;/strong&gt;- &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Java&lt;/strong&gt; is already installed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment variable&lt;/strong&gt; has been set.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To start handling with grid, we need selenium server standalone &lt;strong&gt;JAR&lt;/strong&gt; file. We are going to use &lt;strong&gt;&lt;em&gt;selenium-server-standalone-3.141.59&lt;/em&gt;&lt;/strong&gt;. Download it from &lt;a href="https://jar-download.com/artifacts/org.seleniumhq.selenium/selenium-server/3.141.59/source-code"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here comes Hub and Node concept. A Hub is the central point where nodes will be connected. Hub is something like a docking system, where we can connect several devices via different ports/interfaces to a system. In selenium grid- a node may contain several browsers.&lt;/p&gt;

&lt;p&gt;First, &lt;strong&gt;&lt;em&gt;make a directory&lt;/em&gt;&lt;/strong&gt; and put the &lt;strong&gt;selenium-server-standalone-3.141.59.jar&lt;/strong&gt; there. This step is &lt;strong&gt;&lt;em&gt;very important&lt;/em&gt;&lt;/strong&gt;, because every time we want to start a hub- we must keep the jar file in the same directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 02: Start Hub
&lt;/h2&gt;

&lt;p&gt;Open a cmd terminal window and type-&lt;/p&gt;

&lt;p&gt;&lt;code&gt;java -jar selenium-server-standalone-3.141.59.jar -role hub&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vPEP0v8c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5xktrzidr213s5d8y22.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vPEP0v8c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5xktrzidr213s5d8y22.png" alt="Starting a hub" width="880" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Note:&lt;/strong&gt; By default, it connects to port &lt;code&gt;4444&lt;/code&gt;. We can use any port using  &lt;code&gt;-port&lt;/code&gt; parameter.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;java -jar selenium-server-standalone-3.141.59.jar -role hub -port 5555&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;now, see the grid console at &lt;a href="http://localhost:4444/grid/console/"&gt;http://localhost:4444/grid/console/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U702iJu3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfsi8zywhs971onz4k6y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U702iJu3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfsi8zywhs971onz4k6y.png" alt="Image description" width="880" height="168"&gt;&lt;/a&gt;&lt;br&gt;
The console is &lt;strong&gt;&lt;em&gt;blank&lt;/em&gt;&lt;/strong&gt; as of now, because no node is registered yet.&lt;/p&gt;



&lt;h2&gt;
  
  
  Step 03: Register Node
&lt;/h2&gt;

&lt;p&gt;Now, we need to register some nodes to the hub. Open a new cmd window(in the same directory) and type-&lt;/p&gt;

&lt;p&gt;&lt;code&gt;java -jar selenium-server-standalone-3.141.59.jar -role node -hub http://localhost:4444/grid/register&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A new message apperared in hub cmd after executing the command, see below-&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Bm4r1uSU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fz99p310jbgbe5ngr7eh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Bm4r1uSU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fz99p310jbgbe5ngr7eh.jpg" alt="Register a node: Hub cmd" width="655" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Note:&lt;/strong&gt; We must put &lt;strong&gt;&lt;a href="https://sites.google.com/chromium.org/driver/downloads?authuser=0"&gt;chromedriver.exe&lt;/a&gt;&lt;/strong&gt;/ &lt;strong&gt;&lt;a href="https://github.com/mozilla/geckodriver/releases"&gt;geckodriver.exe&lt;/a&gt;&lt;/strong&gt;/ &lt;strong&gt;&lt;a href="https://www.selenium.dev/downloads/"&gt;iedriver.exe&lt;/a&gt;&lt;/strong&gt; in the same directory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Registering a node has been succeeded, refresh the window in browser-&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L7WLsFAT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qqpndtrst0fbemw82njx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L7WLsFAT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qqpndtrst0fbemw82njx.png" alt="11 browser inst" width="880" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default, it creates &lt;strong&gt;11 browser instances&lt;/strong&gt; (5 chrome, 5 firefox &amp;amp; 1 internet explorer) and it connects with hub using port 4444. To register to a particular port, you can use &lt;strong&gt;-port&lt;/strong&gt; parameter as said before.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;localhost&lt;/em&gt; and IP address:
&lt;/h4&gt;

&lt;p&gt;We are setting up hub and nodes on the same local machine. So that, &lt;em&gt;&lt;code&gt;localhost&lt;/code&gt;&lt;/em&gt; has been used instead of machine IP address. But in real situation, nodes will be connected from different machines with the hub. To find the IP of your machine-&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;open &lt;strong&gt;cmd&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;type &lt;code&gt;ipconfig&lt;/code&gt; &amp;amp; press Enter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;the highlighted IPv4 Address is our machine ip-&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bhoN7-1E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/on6grs2rjsc491w3mt4q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bhoN7-1E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/on6grs2rjsc491w3mt4q.jpg" alt="ipconfig" width="880" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;localhost&lt;/code&gt; will be replaced with IP address along with port no. to register node from a remote machine like this-&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;java -jar selenium-server-standalone-3.141.59.jar -role node -hub http://192.168.251.61:4444/grid/register&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  To create only one instance of a particular browser-
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;java -jar selenium-server-standalone-3.141.59.jar -role node -hub http://localhost:4444/grid/register -browser browserName=chrome&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We can create any browser instance using &lt;code&gt;-browser browserName=chrome&lt;/code&gt; parameter. Change any browser name instead of &lt;code&gt;chrome&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  To create single instance of several browser-
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;java -jar selenium-server-standalone-3.141.59.jar -role node -hub http://localhost:4444/grid/register -browser browserName=chrome -browser browserName=safari -browser browserName=firefox&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Refresh the grid console, the console should look like this-&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IYjC1tYU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/azqorxghp17xruobylgz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IYjC1tYU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/azqorxghp17xruobylgz.png" alt="3 BROWSER" width="880" height="364"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;This is the end of the first tutorial on Selenium Grid. In the next tutorial, we will run a dummy project and learn about- how to use parameters and capabilities to define browser, browser version, max instances, max sessions etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thanks for reading!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>selenium</category>
      <category>grid</category>
    </item>
    <item>
      <title>Page Object Model &amp; PageFactory in Selenium</title>
      <dc:creator>Md Zinnun Uddin</dc:creator>
      <pubDate>Mon, 11 Jul 2022 08:29:00 +0000</pubDate>
      <link>https://dev.to/zinnun/page-object-model-pagefactory-in-selenium-3j4f</link>
      <guid>https://dev.to/zinnun/page-object-model-pagefactory-in-selenium-3j4f</guid>
      <description>&lt;h2&gt;
  
  
  ✒️ What is Page Object Model?
&lt;/h2&gt;

&lt;p&gt;POM is a design pattern in Selenium that creates an &lt;strong&gt;Object Repository&lt;/strong&gt; to store web elements. In POM, we follow the principle of separation of Object Repository and Test Classes. Each object repository only contains the elements of the respective webpage.&lt;/p&gt;



&lt;h2&gt;
  
  
  ✒️ What are the advantages of POM?
&lt;/h2&gt;

&lt;p&gt;✔️ &lt;strong&gt;Easy Maintenance&lt;/strong&gt;: As every page is separate in POM, if there is any change in any webpage that is easy to identify and change. Changes in the object repository don't impact the code elsewhere.&lt;/p&gt;

&lt;p&gt;✔️ &lt;strong&gt;Reusability&lt;/strong&gt;: A single object repository can be used for different TestCases. Also, we can integrate the same POM in Selenium with different types of tests like functional testing and acceptance testing simultaneously. &lt;/p&gt;

&lt;p&gt;✔️ &lt;strong&gt;Readability&lt;/strong&gt;: Testers can easily identify actions that will be performed on a particular webpage.&lt;/p&gt;



&lt;p&gt;⚠️ &lt;strong&gt;&lt;em&gt;verifications&lt;/em&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;em&gt;assertions&lt;/em&gt;&lt;/strong&gt; shouldn't belong to Object Repository ⚠️ &lt;/p&gt;






&lt;h2&gt;
  
  
  ✒️ What is PageFactory in Selenium?
&lt;/h2&gt;

&lt;p&gt;PageFactory is a very &lt;strong&gt;optimized&lt;/strong&gt; way of implementing POM. It is a &lt;code&gt;class&lt;/code&gt; provided by Selenium WebDriver which expands the functionality of plain POM.&lt;/p&gt;



&lt;p&gt;1️⃣ &lt;strong&gt;&lt;code&gt;@FindBy&lt;/code&gt;&lt;/strong&gt;: An annotation used in Page Factory to declare web elements. The @FindBy annotation supports :&lt;code&gt;id, name, className, css, tagName, linkText, partialLinkText, xpath&lt;/code&gt;. Below is an example of declaring an webelement using @FindBy-&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@FindBy(class="elementClass")
WebElement element;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;2️⃣ &lt;strong&gt;&lt;code&gt;initElements()&lt;/code&gt;&lt;/strong&gt;: A &lt;code&gt;static&lt;/code&gt; method in Page Factory class, it instantiate an instance of the given class. Also used to initialize all the web elements defined by @FindBy annotation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public RegistrationPage(WebDriver driver) {           
         this.driver = driver; 
         PageFactory.initElements(driver, this);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;3️⃣ &lt;strong&gt;AjaxElementLocatorFactory&lt;/strong&gt;: &lt;code&gt;AjaxElementLocatorFactory&lt;/code&gt; is &lt;strong&gt;Lazy Loading&lt;/strong&gt; concept in PageFactory. It is used to deal with dynamic elements that change during runtime based on user actions, especially on Ajax-heavy applications. Timeout is also possible to set for a webelement using AjaxElementLocatorFactory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AjaxElementLocatorFactory ajaxFactory = new AjaxElementLocatorFactory(driver, 30);
PageFactory.initElements(ajaxFactory, this);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;







&lt;h2&gt;
  
  
  ✒️ Default behavior of PageFactory:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Web elements declared using &lt;code&gt;@FindBy&lt;/code&gt; are initialized at once and yet not searched in the browser DOM&lt;/li&gt;
&lt;li&gt;WebDriver searches a particular webelement each and every time it is called or any action happened to it.&lt;/li&gt;
&lt;li&gt;For static elements, it provides &lt;code&gt;@CacheLookup&lt;/code&gt; annotation to cache web elements for future uses.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;
  
  
  ✒️ Differences between POM and PageFactory:
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Page Object Model&lt;/th&gt;
&lt;th&gt;PageFactory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Page Object Model is a design pattern.&lt;/td&gt;
&lt;td&gt;PageFactory is a &lt;code&gt;class&lt;/code&gt; that provides an implementation of POM .&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;In POM, individual initialization of every page object is needed.&lt;/td&gt;
&lt;td&gt;In PageFactory, all the page objects are initialized at once by using the initElements() method.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Define web elements using &lt;code&gt;By&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Define web elements using &lt;code&gt;@FindBy&lt;/code&gt; annotation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POM is &lt;strong&gt;not optimal&lt;/strong&gt; as it doesn't support lazy initialization.&lt;/td&gt;
&lt;td&gt;Supports lazy initialization and it is &lt;strong&gt;optimal&lt;/strong&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POM is not capable of handling &lt;code&gt;StaleElementReferenceException&lt;/code&gt;.&lt;/td&gt;
&lt;td&gt;It effeciently handles &lt;code&gt;StaleElementReferenceException&lt;/code&gt; by searching everytime when  any stale element is called.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;






&lt;h2&gt;
  
  
  ✒️ &lt;em&gt;@CacheLookUp&lt;/em&gt; annotation:
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@CacheLookUp&lt;/code&gt; annotation is used to keep a cache of WebElement on its first arrival on the webpage instead of searching over and over again, usually used for elements that never change.&lt;/p&gt;

&lt;p&gt;A findElement() &lt;strong&gt;REST Request&lt;/strong&gt; is sent to the WebDriver every time a WebElement is called from page object repository. This satisfies one of the important Pagefactory benefits of looking for the newest version of webelements after page loading. But, it makes the process slow and time-consuming(a lot obviously!). Here, &lt;code&gt;@CacheLookUp&lt;/code&gt; comes to solve the problem.&lt;/p&gt;



&lt;h2&gt;
  
  
  ✒️ When not to use &lt;em&gt;@CacheLookUp&lt;/em&gt;?
&lt;/h2&gt;

&lt;p&gt;It is not suitable for elements that are dynamic in nature. For &lt;strong&gt;AJAX&lt;/strong&gt; based applications, it may not work where the &lt;strong&gt;DOM&lt;/strong&gt; frequently changes based on user interaction. Upon using @CacheLookUp annotation, WebDriver may throw &lt;strong&gt;StaleElementExceptions&lt;/strong&gt;.&lt;/p&gt;






</description>
      <category>testing</category>
      <category>selenium</category>
      <category>pom</category>
      <category>pagefactory</category>
    </item>
  </channel>
</rss>
