<?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: Arvind Choudhary</title>
    <description>The latest articles on DEV Community by Arvind Choudhary (@arvind_choudhary).</description>
    <link>https://dev.to/arvind_choudhary</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%2F846577%2F53c3a2f3-1bef-4fff-902d-92fa4472399f.jpeg</url>
      <title>DEV Community: Arvind Choudhary</title>
      <link>https://dev.to/arvind_choudhary</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arvind_choudhary"/>
    <language>en</language>
    <item>
      <title>Docker Image of your Testing Project / Dockerise test execution</title>
      <dc:creator>Arvind Choudhary</dc:creator>
      <pubDate>Thu, 03 Nov 2022 16:28:39 +0000</pubDate>
      <link>https://dev.to/arvind_choudhary/docker-image-of-your-testing-project-dockerise-test-execution-3o02</link>
      <guid>https://dev.to/arvind_choudhary/docker-image-of-your-testing-project-dockerise-test-execution-3o02</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa76lhpumi6q4ormzt2y6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa76lhpumi6q4ormzt2y6.png" alt="Docker image"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I previously wrote about docker &amp;amp; testng, how it can be useful? but did you ever feel that why should we keep running tests in complex manner( on local machine/on virtual machine)? Can we make it simple enough for everyone to run tests with ease?!&lt;/p&gt;

&lt;p&gt;What if we have a docker-image of our test code which when executed will test our app. you just have to do &lt;code&gt;docker run &amp;lt;image-name&amp;gt;&lt;/code&gt; and that's it. your scripts shall trigger inside container and on completion you should be able to get test status on console!&lt;/p&gt;

&lt;p&gt;Few advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Anyone can execute scripts &amp;amp; get test results.&lt;/li&gt;
&lt;li&gt;Development/Testing knowledge is not required.&lt;/li&gt;
&lt;li&gt;Test execution is completely isolated.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Github repo: &lt;a href="https://github.com/Arvind142/TestNG-Modular-Automation-Framework" rel="noopener noreferrer"&gt;Arvind142/TestNG-Modular-Automation-Framework&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Start with creating test suite, verifying POM!
&lt;/h2&gt;

&lt;h3&gt;
  
  
  testng.xml
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br&gt;
&amp;lt;!DOCTYPE suite SYSTEM "&lt;a href="https://testng.org/testng-1.0.dtd" rel="noopener noreferrer"&gt;https://testng.org/testng-1.0.dtd&lt;/a&gt;"&amp;gt;&lt;br&gt;
&amp;lt;suite name="Suite"&amp;gt;&lt;br&gt;
    &amp;lt;!-- Listeners to help with reporting --&amp;gt;&lt;br&gt;
    &amp;lt;listeners&amp;gt;&lt;br&gt;
        &amp;lt;!-- Listener Class declaration --&amp;gt;&lt;br&gt;
    &amp;lt;/listeners&amp;gt;&lt;br&gt;
    &amp;lt;test name="Test"&amp;gt;&lt;br&gt;
        &amp;lt;packages&amp;gt;&lt;br&gt;
            &amp;lt;!-- test package declaration --&amp;gt;&lt;br&gt;
            &amp;lt;package name="com.core.test_package.*"&amp;gt;&amp;lt;/package&amp;gt;&lt;br&gt;
        &amp;lt;/packages&amp;gt;&lt;br&gt;
    &amp;lt;/test&amp;gt; &amp;lt;!-- Test --&amp;gt;&lt;br&gt;
&amp;lt;/suite&amp;gt; &amp;lt;!-- Suite --&amp;gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Pom.xml&lt;br&gt;
&lt;/h3&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;&amp;lt;build&amp;gt;&lt;br&gt;
    &amp;lt;pluginManagement&amp;gt;&lt;br&gt;
        &amp;lt;plugins&amp;gt;&lt;br&gt;
            &amp;lt;plugin&amp;gt;&lt;br&gt;
                &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;&lt;br&gt;
                &amp;lt;configuration&amp;gt;&lt;br&gt;
                    &amp;lt;suiteXmlFiles&amp;gt;&lt;br&gt;
                        &amp;lt;suiteXmlFile&amp;gt;testng.xml&amp;lt;/suiteXmlFile&amp;gt;&lt;br&gt;
                    &amp;lt;/suiteXmlFiles&amp;gt;&lt;br&gt;
                &amp;lt;/configuration&amp;gt;&lt;br&gt;
            &amp;lt;/plugin&amp;gt;&lt;br&gt;
        &amp;lt;/plugins&amp;gt;&lt;br&gt;
    &amp;lt;/pluginManagement&amp;gt;&lt;br&gt;
&amp;lt;/build&amp;gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Trigger them to Verify it's working.&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;mvn clean test -Dsurefire.suiteXmlFiles=/path/to/testng.xml&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Create image of your code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Dockerfile
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;h1&gt;
  
  
  Base image
&lt;/h1&gt;

&lt;p&gt;FROM maven:3.8.5-openjdk-11-slim&lt;/p&gt;
&lt;h1&gt;
  
  
  Argument with default value
&lt;/h1&gt;

&lt;p&gt;ARG suiteFile=testng.xml&lt;/p&gt;
&lt;h1&gt;
  
  
  Copy code from local to image
&lt;/h1&gt;

&lt;p&gt;COPY ./ /app&lt;/p&gt;
&lt;h1&gt;
  
  
  Specify working directory
&lt;/h1&gt;

&lt;p&gt;WORKDIR /app&lt;/p&gt;
&lt;h1&gt;
  
  
  Execute command at creation of image
&lt;/h1&gt;

&lt;p&gt;RUN mvn clean compile&lt;/p&gt;
&lt;h1&gt;
  
  
  Command to be executed at start of container
&lt;/h1&gt;

&lt;p&gt;CMD mvn test -Dsurefire.suiteXmlFiles=$suiteFile -e&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Build your image&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;docker build -t arvindc142/framework:v1 .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqzkr27iqlv4t2nejbv1f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqzkr27iqlv4t2nejbv1f.png" alt="Build SS"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Run you image
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;docker run arvindc142/framework:v1&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Run different test suite (other than testng.xml, which was metioned as default suite)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;docker run -e suiteFile=testng-karate.xml arvindc142/framework:v1&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Remember to publish image to image repo so that it is available for others to leverage.
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;docker image push arvindc142/framework:v1&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What about test reports?
&lt;/h2&gt;

&lt;p&gt;since tests were executed in container then reports are within container, how can i get them? Volume Mapping&lt;/p&gt;

&lt;h3&gt;
  
  
  Volume Mapping
&lt;/h3&gt;

&lt;p&gt;Volumes are the preferred mechanism for persisting data generated by and used by Docker containers. While bind mounts are dependent on the directory structure and OS of the host machine, volumes are completely managed by Docker.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; In my case reports are generated in test-output folder, I’ll map test-output of my image with my machine’s folder (i.e., test-results) so that I can get test result there! (&lt;strong&gt;Use PowerShell on windows)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -v $PWD/test-results:/app/test-output arvindc142/framework:v1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Before Snapshot:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffic2c09wlmo88ginyvnx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffic2c09wlmo88ginyvnx.png" alt="Before SS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;After executing docker run with -v option:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqskumsyq1hepo5qomunp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqskumsyq1hepo5qomunp.png" alt="After ss"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fue4hhtllovb0fyk1rv6t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fue4hhtllovb0fyk1rv6t.png" alt="RPT"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  BONUS!!!
&lt;/h2&gt;

&lt;p&gt;Let’s add selenium grid with code for UI test script execution.&lt;/p&gt;

&lt;p&gt;above setup were only for test execution it didn’t cover selenium-based UI script execution.&lt;/p&gt;

&lt;p&gt;Note: Remote url will be &lt;a href="http://selenium-hub:4444/wd/hub" rel="noopener noreferrer"&gt;http://selenium-hub:4444/wd/hub&lt;/a&gt; inside framework container.&lt;/p&gt;

&lt;p&gt;Container can connect to hub container with host as selenium-hub, i’ve also exposed port 4444 to watch script execution from your machine. you can access hub with &lt;a href="http://localhost:4444/ui" rel="noopener noreferrer"&gt;http://localhost:4444/ui&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Hub Snapshot:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5wylw180qcj8knybbna.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5wylw180qcj8knybbna.png" alt="grid"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker-compose for Selenium grid and our test script execution
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;version: '3.7'&lt;/p&gt;
&lt;h1&gt;
  
  
  compose version details
&lt;/h1&gt;

&lt;p&gt;services:&lt;br&gt;
  #-SELENIUM GRID SETUP FOR AUTOMATION EXECUTION-&lt;br&gt;
  selenium-hub:&lt;br&gt;
    image: selenium/hub:latest&lt;br&gt;
    container_name: selenium-hub&lt;br&gt;
    ports:&lt;br&gt;
      - 4444:4444&lt;br&gt;
  chrome:&lt;br&gt;
    image: selenium/node-chrome:latest&lt;br&gt;
    shm_size: 2gb&lt;br&gt;
    depends_on:&lt;br&gt;
      - selenium-hub&lt;br&gt;
    environment:&lt;br&gt;
      - SE_EVENT_BUS_HOST=selenium-hub&lt;br&gt;
      - SE_EVENT_BUS_PUBLISH_PORT=4442&lt;br&gt;
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443&lt;br&gt;
  edge:&lt;br&gt;
    image: selenium/node-edge:latest&lt;br&gt;
    shm_size: 2gb&lt;br&gt;
    depends_on:&lt;br&gt;
      - selenium-hub&lt;br&gt;
    environment:&lt;br&gt;
      - SE_EVENT_BUS_HOST=selenium-hub&lt;br&gt;
      - SE_EVENT_BUS_PUBLISH_PORT=4442&lt;br&gt;
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443&lt;br&gt;
  firefox:&lt;br&gt;
    image: selenium/node-firefox:latest&lt;br&gt;
    shm_size: 2gb&lt;br&gt;
    depends_on:&lt;br&gt;
      - selenium-hub&lt;br&gt;
    environment:&lt;br&gt;
      - SE_EVENT_BUS_HOST=selenium-hub&lt;br&gt;
      - SE_EVENT_BUS_PUBLISH_PORT=4442&lt;br&gt;
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443&lt;br&gt;
  #-SELENIUM GRID services ended-&lt;/p&gt;

&lt;p&gt;#-Framework image-&lt;br&gt;
  # service name(container name)&lt;br&gt;
  modular-automation-framework:&lt;br&gt;
    # which container to use for building&lt;br&gt;
    image: arvindc142/framework:v1&lt;br&gt;
    # to copy project into container&lt;br&gt;
    volumes:&lt;br&gt;
      - './test-results/:/app/test-output/'&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  To spin up all containers&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;docker-compose up -d&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhj4jsxp133oa5hiwepk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhj4jsxp133oa5hiwepk.png" alt="spin up"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Get all containers
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;docker ps -a&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Print container logs on console
&lt;/h2&gt;

&lt;p&gt;you can get container-id’s with docker ps command&lt;br&gt;
&lt;code&gt;docker logs -f &amp;lt;container-id&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  To stop &amp;amp; remove containers
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;docker-compose down&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi306o53q4wu5cv27pk5w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi306o53q4wu5cv27pk5w.png" alt="Close DOwn"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/testng-run-command-line" rel="noopener noreferrer"&gt;Run TestNG from commandline&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Arvind142/TestNG-Modular-Automation-Framework" rel="noopener noreferrer"&gt;Github TestNG Project&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yipl.com.np/volume-mapping-a-way-to-make-persistent-data-storage-in-docker-6a47c951a0e7" rel="noopener noreferrer"&gt;Volume Mapping&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/SeleniumHQ/docker-selenium" rel="noopener noreferrer"&gt;Docker-Selenium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hub.docker.com/r/arvindc142/framework/tags" rel="noopener noreferrer"&gt;docker hub arvindc142/framework&lt;/a&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>testing</category>
      <category>docker</category>
      <category>testautomation</category>
    </item>
    <item>
      <title>TestNG testing framework — Parameterization</title>
      <dc:creator>Arvind Choudhary</dc:creator>
      <pubDate>Wed, 11 May 2022 05:41:31 +0000</pubDate>
      <link>https://dev.to/arvind_choudhary/testng-testing-framework-parameterization-cep</link>
      <guid>https://dev.to/arvind_choudhary/testng-testing-framework-parameterization-cep</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DwdEURxg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f1td66oz4wtklxy8dd74.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DwdEURxg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f1td66oz4wtklxy8dd74.png" alt="TestNG" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Parameterization?
&lt;/h3&gt;

&lt;p&gt;Whenever we define any parameters on any of our methods, it means we are parametrizing that method. e.g. assuming areaOfSquare(int side);takes one argument which is integer and returns ares of square. it also allows you to use the same method for N. no of values.&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt; method of TestNG supports parameterization, which in simple terms means it allows us to pass values to our test method at runtime.&lt;/p&gt;




&lt;h3&gt;
  
  
  Ways to Parameterize &lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt; Method
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;@DataProvider&lt;/li&gt;
&lt;li&gt;@Parameters&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Parameterization with @DataProvider annotation
&lt;/h3&gt;

&lt;p&gt;Always remember to use below 2 if plan on parameterizing your &lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt; with data provider.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;@DataProvider annotation with name attribute.&lt;/li&gt;
&lt;li&gt;
&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt; with attribute dataProvider having same value as specified for above step.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Code:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class DataProviderDemo {
    /**
     * always use name attribute for your dataProvider(), you can have
     * N. no of dataprovider in your Test class and with the help of dataprovider attribute of @Test(refer to line 57)
     * you can specify which dataprovider method to use.
     */

    // always returns 2D Object array
    @DataProvider(name = "testData")
    public Object[][] dataProvider(){
        // 2D Object array initialized
        Object[][] objectArray = new Object[2][2];

        /**
         * 2D Array structure
         *      |   abc     |   cde     |
         *      |   efg     |   hij     |
         *
         * what @data provider will do here is that it will send data of one row at a time to test method,
         *  then next row and so on.
         *
         *  no. of rows = no. of times your @Test will get executed
         */

        // adding value in objectArray
        objectArray[0][0] = "abc";
        objectArray[0][1] = "cde";
        objectArray[1][0] = "efg";
        objectArray[1][1] = "hij";

        // return 2D Object array
        return objectArray;
    }

    /**
     * make sure to use dataProvider attribute on your @Test annotation(refer to line 57),
     *
     * Also change you method signature according to what you are passing from your dataProvider,
     * if you are not sure on what you should do then you can also keep your parameter type as String &amp;amp;
     * testng would typecase it for you to string.
     *
     * no. of parameters on @test method should be same as no. of Object defined on your object array(column-wise).
     * ref line 19, we have 2 columns and 2 rows. so you should have 2 parmaters(2 columns) in your method signature.
     * (ref line no. 58)
     * -------------------------OR---------------------------
     *
     * use (String... args), here dont have to specify each parameter,
     * you will get one array which is args and you can work with it with the help of index,
     * each parameter will be stored on one index
     * assuming current case your array will have 2 indexes [0 &amp;amp; 1]
     * where 0th index would hold first value and 1st index would hold second value.
     * (ref line no. 63)
     */
    @Test(dataProvider = "testData") // line 57
    public void testMethod(String val1, String val2){ //line 58
        System.out.println("testMethod called with ["+val1+", "+val2+"]");
    }

    @Test(dataProvider = "testData")
    public void testMethod1(String... args){ //line 63
        System.out.println("testMethod1 called with ["+args[0]+", "+args[1]+"]");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Output:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;testMethod called with [abc, cde]
testMethod called with [efg, hij]
testMethod1 called with [abc, cde]
testMethod1 called with [efg, hij]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Parameterization with @Parameters annotation
&lt;/h3&gt;

&lt;p&gt;Passing value with @Parameters is bit tricky here as we will be passing values from testng.xml&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TestNG.xml&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"&amp;gt;
&amp;lt;suite name="Suite"&amp;gt;
    &amp;lt;test name="Test1"&amp;gt;
        &amp;lt;parameter name="value1" value="abc"&amp;gt;&amp;lt;/parameter&amp;gt;
        &amp;lt;parameter name="value2" value="cde"&amp;gt;&amp;lt;/parameter&amp;gt;
        &amp;lt;parameter name="value3" value="klm"&amp;gt;&amp;lt;/parameter&amp;gt;
        &amp;lt;classes&amp;gt;
            &amp;lt;class name="ParametersDemo" &amp;gt;&amp;lt;/class&amp;gt;
        &amp;lt;/classes&amp;gt;
    &amp;lt;/test&amp;gt; &amp;lt;!-- Test --&amp;gt;
    &amp;lt;test name="Test2"&amp;gt;
        &amp;lt;parameter name="value1" value="efg"&amp;gt;&amp;lt;/parameter&amp;gt;
        &amp;lt;parameter name="value2" value="hij"&amp;gt;&amp;lt;/parameter&amp;gt;
        &amp;lt;classes&amp;gt;
            &amp;lt;class name="ParametersDemo" &amp;gt;&amp;lt;/class&amp;gt;
        &amp;lt;/classes&amp;gt;
    &amp;lt;/test&amp;gt; &amp;lt;!-- Test --&amp;gt;
&amp;lt;/suite&amp;gt; &amp;lt;!-- Suite --&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Script&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class ParametersDemo {
    /**
     *
     *  in @Parameters you should specify parameter name
     *  and same should be present in testng.xml.
     *  refer to line 5 &amp;amp; 13 of testng.xml
     *
     * @param val1 parameter should be specified in test.xml
     * @param val2 parameter should be specified in test.xml
     * @param val3 is Optional, if specified well it would take specified value else defualt value
     *             refer to line 15, we have use @Optional
     */
    @Test
    @Parameters({"value1","value2","value3"})
    public void testMethod(String val1,String val2,@Optional("default") String val3){
        System.out.println("testMethod called with ["+val1+","+val2+","+val3+"]");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;testMethod called with [abc,cde,klm]
testMethod called with [efg,hij,default]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you see above for second test tag we only specified 2 parameters instead of 3 and because of @Optional usage we didn’t get any error.&lt;/p&gt;

&lt;p&gt;if you would have not specified @Optional and you didn’t specify parameter in testng.xml you will below error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;testMethod called with [abc,cde,klm]
org.testng.TestNGException: 
Parameter 'value3' is required by @Test on method testMethod but has not been marked @Optional or defined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Useful URLs:&lt;br&gt;
&lt;a href="https://www.javatpoint.com/testng-parameters"&gt;Javatpoint parameters&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>automationtestin</category>
      <category>test</category>
      <category>testng</category>
    </item>
    <item>
      <title>TestNG testing framework - Introduction</title>
      <dc:creator>Arvind Choudhary</dc:creator>
      <pubDate>Sun, 08 May 2022 12:13:41 +0000</pubDate>
      <link>https://dev.to/arvind_choudhary/testng-testing-framework-8hi</link>
      <guid>https://dev.to/arvind_choudhary/testng-testing-framework-8hi</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t6ABKdXs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6qhmpxoly7ujuasiulgn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t6ABKdXs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6qhmpxoly7ujuasiulgn.png" alt="TestNG logo" width="880" height="319"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  What is a Testing Framework?
&lt;/h3&gt;

&lt;p&gt;A testing framework is a set of guidelines or rules used for creating and designing test cases. A framework is comprised of a combination of practices and tools that are designed to help QA professionals test more efficiently.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Popular available options:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;JUnit&lt;/li&gt;
&lt;li&gt;NUnit&lt;/li&gt;
&lt;li&gt;TestNG&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Why TestNG?
&lt;/h3&gt;

&lt;p&gt;TestNG is a testing framework inspired by JUnit and NUnit but introduces some new functionalities that make it more powerful and easier to use, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Annotations.&lt;/li&gt;
&lt;li&gt;Run your tests in arbitrarily big thread pools with various policies available (all methods in their thread, one thread per test class, etc…).&lt;/li&gt;
&lt;li&gt;Test that your code is multithread safe.&lt;/li&gt;
&lt;li&gt;Flexible test configuration.&lt;/li&gt;
&lt;li&gt;Support for data-driven testing (with @DataProvider).&lt;/li&gt;
&lt;li&gt;Support for parameters.&lt;/li&gt;
&lt;li&gt;Powerful execution model (no more TestSuite).&lt;/li&gt;
&lt;li&gt;Supported by a variety of tools and plug-ins (Eclipse, IDEA, Maven, etc…).&lt;/li&gt;
&lt;li&gt;Embeds BeanShell for further flexibility.&lt;/li&gt;
&lt;li&gt;Default JDK functions for runtime and logging (no dependencies).&lt;/li&gt;
&lt;li&gt;Dependent methods for application server testing.
TestNG is designed to cover all categories of tests: unit, functional, end-to-end, integration, etc…&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Annotations in TestNG
&lt;/h3&gt;

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




&lt;h3&gt;
  
  
  Assertions
&lt;/h3&gt;

&lt;p&gt;Assertions in TestNG are a way to verify that the expected result and the actual result match or not.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Expected Result&lt;/strong&gt;: expected outcome at a point in time while testing application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actual Result&lt;/strong&gt;: actual outcome at a point in time while testing application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Assert.assertEquals(actualOutcome,expectedOutcome);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Types Of Assertions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Hard Assertion&lt;/strong&gt;: Hard Asserts are those asserts that stop the test execution when an assert statement fails, and the subsequent assert statements are therefore not validated.&lt;br&gt;
&lt;strong&gt;Soft Assertions&lt;/strong&gt;: In soft asserts, the subsequent assertions keep on running even though one assert validation fails, i.e., the test execution does not stop.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Hard Assert
Assert.assertEquals(actualResult,expectedResult);
# Soft Assert
SoftAssert softassert = new SoftAssert();
softassert.assertEquals(actualResult, expecetedResult);
softassert.assertAll();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Example Usage
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;pom.xml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.testng&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;testng&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;7.5&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;only &lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;&lt;/strong&gt; annotated methods are called test should hold test scripts, whereas &lt;strong&gt;@BeforeMethod/@AfterMethod&lt;/strong&gt; methods should be used for setting up prerequisites &amp;amp; cleaning up for each tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

public class Runner {
    @BeforeTest
    public void beforeTest(){
        System.out.println("method to be executed before test");
    }

    @Test
    public void test(){
        System.out.println("test method");
    }

    @AfterTest
    public void afterTest(){
        System.out.println("method to be executed after test");
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;method to be executed before test
test method
method to be executed after test
===============================================
Default Suite
Total tests run: 1, Passes: 1, Failures: 0, Skips: 0
===============================================
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Few useful URLs:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://testng.org/doc/"&gt;TestNG webpage&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.javatpoint.com/testng-tutorial"&gt;Javatpoint tutorial&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>testng</category>
      <category>bugs</category>
      <category>defect</category>
    </item>
    <item>
      <title>Why to use Loggers?</title>
      <dc:creator>Arvind Choudhary</dc:creator>
      <pubDate>Sun, 01 May 2022 13:07:19 +0000</pubDate>
      <link>https://dev.to/arvind_choudhary/why-to-use-loggers-3b7</link>
      <guid>https://dev.to/arvind_choudhary/why-to-use-loggers-3b7</guid>
      <description>&lt;h2&gt;
  
  
  Loggers
&lt;/h2&gt;

&lt;p&gt;In Java, logging is an important feature that helps developers to trace out the errors. Java is the programming language that comes with the logging approach. It provides a Logging API that was introduced in Java 1.4 version. It provides the ability to capture the log file.&lt;/p&gt;




&lt;h3&gt;
  
  
  Components of Loggers
&lt;/h3&gt;

&lt;p&gt;Logger — recorder.&lt;br&gt;
Handlers or Appender — Where to send logs(console, file, etc.)&lt;br&gt;
Formatters or Layouts — How to display logs.&lt;/p&gt;




&lt;h3&gt;
  
  
  Different Loggers
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Log4j: Apache Log4j is an open-source Java-based logging utility.&lt;/li&gt;
&lt;li&gt;SLF4J: It stands for Simple Logging Facade for Java (SLF4J). It is an abstraction layer for multiple logging frameworks such as Log4j, Logback, and java.util.logging.&lt;/li&gt;
&lt;li&gt;Logback: It is an open-source project designed as a successor to Log4j version 1 before Log4j version 2 was released.&lt;/li&gt;
&lt;li&gt;tinylog(tinylog): It is a light weighted and open-source logger.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Why Loggers?
&lt;/h3&gt;

&lt;p&gt;While building your application/framework, you would often face errors which have to be debugged. So, with the help of logs, we can easily get information about what is happening within our app or framework with a record of errors and unusual circumstances. Now, it might strike your mind that, &lt;strong&gt;why not use the System.out.print() statement in Java. Well, the problem with these statements is that log messages will be printed only on the console. So, once you close console, automatically, all the logs will be lost&lt;/strong&gt;. Therefore, logs will be not be stored permanently, and are displayed one by one, as it is a single-threaded environment.&lt;br&gt;
In this post we would be using Logback logger library for our demo.&lt;/p&gt;




&lt;h4&gt;
  
  
  Logger Level Description:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs9lqlhwhemvmr9s6gg2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs9lqlhwhemvmr9s6gg2s.png" alt="Logger Description"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Maven dependency:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic --&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;ch.qos.logback&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;logback-classic&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.2.11&amp;lt;/version&amp;gt;
    &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  logback-test.xml ( convention is to keep it in resources folder)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;configuration&amp;gt;

    &amp;lt;!-- Console Appender --&amp;gt;
    &amp;lt;appender name="console-appender" class="ch.qos.logback.core.ConsoleAppender"&amp;gt;
        &amp;lt;encoder&amp;gt;
            &amp;lt;pattern&amp;gt;%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n&amp;lt;/pattern&amp;gt;
        &amp;lt;/encoder&amp;gt;
    &amp;lt;/appender&amp;gt;


    &amp;lt;!-- File Appender --&amp;gt;
    &amp;lt;appender name="file-appender" class="ch.qos.logback.core.FileAppender"&amp;gt;
        &amp;lt;encoder&amp;gt;
            &amp;lt;pattern&amp;gt;%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n&amp;lt;/pattern&amp;gt;
        &amp;lt;/encoder&amp;gt;
        &amp;lt;file&amp;gt;trace.log&amp;lt;/file&amp;gt;
        &amp;lt;append&amp;gt;false&amp;lt;/append&amp;gt;
    &amp;lt;/appender&amp;gt;

    &amp;lt;root level="ALL"&amp;gt;
        &amp;lt;appender-ref ref="console-appender" /&amp;gt;
        &amp;lt;appender-ref ref="file-appender" /&amp;gt;
    &amp;lt;/root&amp;gt;

&amp;lt;/configuration&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  MainClass.java
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MainClass {
    public static void main(String[] args) {
        // initializing logger
        Logger logger = LoggerFactory.getLogger(MainClass.class);
        logger.trace("trace-log");
        logger.debug("debug-log");
        logger.info("info-log");
        logger.warn("warn-log");
        logger.error("error-log");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;In our case we are using 2 Appenders:&lt;br&gt;
Console Appender : To print logs onto console.&lt;br&gt;
File Appender : To send logs to file.&lt;br&gt;
kindly refer to logback-test.xml where we have mentioned 2 different appenders and log format.&lt;/p&gt;

&lt;h4&gt;
  
  
  Console print:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;21:21:32.722 [main] TRACE MainClass - trace-log
21:21:32.722 [main] DEBUG MainClass - debug-log
21:21:32.722 [main] INFO  MainClass - info-log
21:21:32.727 [main] WARN  MainClass - warn-log
21:21:32.727 [main] ERROR MainClass - error-log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  trace.log
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;21:21:32.722 [main] TRACE MainClass - trace-log
21:21:32.722 [main] DEBUG MainClass - debug-log
21:21:32.722 [main] INFO  MainClass - info-log
21:21:32.727 [main] WARN  MainClass - warn-log
21:21:32.727 [main] ERROR MainClass - error-log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Getting started with WDM(WebDriverManager)</title>
      <dc:creator>Arvind Choudhary</dc:creator>
      <pubDate>Sun, 24 Apr 2022 14:49:50 +0000</pubDate>
      <link>https://dev.to/arvind_choudhary/getting-started-with-wdmwebdrivermanager-5h6g</link>
      <guid>https://dev.to/arvind_choudhary/getting-started-with-wdmwebdrivermanager-5h6g</guid>
      <description>&lt;p&gt;Hello Readers,&lt;/p&gt;

&lt;p&gt;Whenever we talk about Automation Testing(Browser Automation) we should have a few things in place:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Browser (Should be on the system path).&lt;/li&gt;
&lt;li&gt;Driver Executable (Should be on the system path), Driver Executable version should be the same as Browser Version.&lt;/li&gt;
&lt;li&gt;Automation Library(In our case Selenium).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;strong&gt;second part&lt;/strong&gt; of Point 2 is &lt;strong&gt;tedious&lt;/strong&gt;. Nowadays we get at least one browser update every month or two, so we have to download the driver executable which is released for that particular browser version.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--teoGbM8c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0as43y13e3wqz0re5bf8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--teoGbM8c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0as43y13e3wqz0re5bf8.png" alt="Chrome release channel information - source:wikipedia" width="700" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;As shown in fig, chrome releases multiple browsers update each month in stable/beta/developer channels.&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  So, How can we make our test project in such a way that there should be no manual intervention required in getting the correct driver executables for different browsers?
&lt;/h3&gt;

&lt;p&gt;WDM(WebDriverManager) utility which is created by &lt;a href="https://github.com/bonigarcia"&gt;bonigarcia&lt;/a&gt; could help us in automatically downloading driver version based on different browsers, browser version and OS's .&lt;/p&gt;




&lt;h3&gt;
  
  
  WebDriverManager
&lt;/h3&gt;

&lt;p&gt;WebDriverManager is an open-source Java library that carries out the management (i.e., download, setup, and maintenance) of the drivers required by Selenium WebDriver (e.g., chromedriver, geckodriver, msedgedriver, etc.) in a fully automated manner. In addition, as of version 5, WebDriverManager provides other relevant features, such as the capability to discover browsers installed in the local system, building WebDriver objects (such as ChromeDriver, FirefoxDriver, EdgeDriver, etc.), and running browsers in Docker containers seamlessly.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;Maven dependency:&lt;/em&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
 &amp;lt;groupId&amp;gt;io.github.bonigarcia&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;webdrivermanager&amp;lt;/artifactId&amp;gt;
 &amp;lt;version&amp;gt;5.1.1&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;em&gt;Pom.xml:&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;minimal pom.xml dependency list for browser automation with WDM and selenium.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TvAMIvVR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0g2hjbrnnnkox3kcd96x.png" alt="pom.xml" width="700" height="268"&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Script (java):&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;I’ve used java language to use with selenium.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0hIuA4Xk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vix3b3ae337t5u1tewjv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0hIuA4Xk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vix3b3ae337t5u1tewjv.png" alt="script" width="700" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Examples of how to set up driver executable for different browsers.&lt;br&gt;
&lt;code&gt;WebDriverManager.chromedriver().setup();&lt;/code&gt;&lt;br&gt;
&lt;code&gt;WebDriverManager.edgedriver().setup();&lt;/code&gt;&lt;br&gt;
&lt;code&gt;WebDriverManager.firefoxdriver().setup();&lt;/code&gt;&lt;br&gt;
How to specify which driver executable we want (Explicit specification, Optional)&lt;br&gt;
&lt;code&gt;WebDriverManager.firefoxdriver().browserVersion("100").setup();&lt;/code&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;Console print:&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WBrba_a6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k513odvbs06w4o48hcx4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WBrba_a6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k513odvbs06w4o48hcx4.png" alt="Console print" width="700" height="249"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;em&gt;Useful URL's&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/bonigarcia"&gt;bonigarcia's github page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bonigarcia.dev/webdrivermanager"&gt;WebDriverManager website&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/bonigarcia/webdrivermanager"&gt;WebDriverManager repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>selenium</category>
      <category>testautomation</category>
      <category>browserautomation</category>
    </item>
    <item>
      <title>Selenium Grid Setup with Docker</title>
      <dc:creator>Arvind Choudhary</dc:creator>
      <pubDate>Fri, 15 Apr 2022 05:53:25 +0000</pubDate>
      <link>https://dev.to/arvind_choudhary/selenium-grid-setup-with-docker-59cn</link>
      <guid>https://dev.to/arvind_choudhary/selenium-grid-setup-with-docker-59cn</guid>
      <description>&lt;p&gt;Hello readers,&lt;/p&gt;

&lt;p&gt;from past few days I've been thinking about reducing automation test execution time by creating an environment where I could perform cross-browser and/or parallel execution.&lt;/p&gt;

&lt;p&gt;I came-across once solution where we could leverage docker to setup selenium grid on our local machine.&lt;/p&gt;




&lt;h3&gt;
  
  
  Perquisite(software)
&lt;/h3&gt;

&lt;p&gt;Docker&lt;/p&gt;

&lt;h3&gt;
  
  
  Commands to pull required images
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;pulling hub image&lt;br&gt;
&lt;code&gt;docker pull selenium/hub:latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;pulling node-chrome&lt;br&gt;
&lt;code&gt;docker pull selenium/node-chrome:latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;pulling node-firefox&lt;br&gt;
&lt;code&gt;docker pull selenium/node-firefox:latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;pulling node-edge&lt;br&gt;
&lt;code&gt;docker pull selenium/node-edge:latest&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Commands to setup grid
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;creating custom network&lt;br&gt;
&lt;code&gt;docker network create grid&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;running hub image&lt;br&gt;
&lt;code&gt;docker run -d --rm -p 4442–4444:4442–4444 --net grid --name selenium-hub selenium/hub:latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;running node-chrome image&lt;br&gt;
&lt;code&gt;docker run -d --rm --net grid -e SE_EVENT_BUS_HOST=selenium-hub --name node-chrome -e SE_EVENT_BUS_PUBLISH_PORT=4442 -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 selenium/node-chrome:latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;running node-edge image&lt;br&gt;
&lt;code&gt;docker run -d --rm --net grid -e SE_EVENT_BUS_HOST=selenium-hub --name node-edge -e SE_EVENT_BUS_PUBLISH_PORT=4442 -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 selenium/node-edge:latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;running node-firefox image&lt;br&gt;
&lt;code&gt;docker run -d --rm --net grid -e SE_EVENT_BUS_HOST=selenium-hub --name node-firefox -e SE_EVENT_BUS_PUBLISH_PORT=4442 -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 selenium/node-firefox:latest&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Check container status
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;docker ps&lt;/code&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gtbea73A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8lhsof9ekt08a97o6hf6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gtbea73A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8lhsof9ekt08a97o6hf6.png" alt="Image description" width="880" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;all your containers should have &lt;strong&gt;Status&lt;/strong&gt; as &lt;strong&gt;Up&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Grid UI:
&lt;/h3&gt;

&lt;p&gt;navigate to &lt;code&gt;http://localhost:4444/ui/index.html&lt;/code&gt; on your machine to open grid UI&lt;/p&gt;

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




&lt;h3&gt;
  
  
  Increasing instances for parallel execution on same browser
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;creating custom network&lt;br&gt;
&lt;code&gt;docker network create grid&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;running hub image&lt;br&gt;
&lt;code&gt;docker run -d --rm -p 4442–4444:4442–4444 --net grid --name selenium-hub selenium/hub:latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;running node-chrome image&lt;br&gt;
&lt;code&gt;docker run -d --rm --net grid -e SE_EVENT_BUS_HOST=selenium-hub --name node-chrome --shm-size="2g"  -e SE_NODE_MAX_SESSIONS=8 -e SE_EVENT_BUS_PUBLISH_PORT=4442 -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 selenium/node-chrome:latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;running node-edge image&lt;br&gt;
&lt;code&gt;docker run -d --rm --net grid -e SE_EVENT_BUS_HOST=selenium-hub --name node-edge --shm-size="2g" -e SE_NODE_MAX_SESSIONS=8 -e SE_EVENT_BUS_PUBLISH_PORT=4442 -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 selenium/node-edge:latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;running node-firefox image&lt;br&gt;
&lt;code&gt;docker run -d --rm --net grid -e SE_EVENT_BUS_HOST=selenium-hub --name node-firefox --shm-size="2g" -e SE_NODE_MAX_SESSIONS=8 -e SE_EVENT_BUS_PUBLISH_PORT=4442 -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 selenium/node-firefox:latest&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Grid UI:
&lt;/h3&gt;

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




&lt;h3&gt;
  
  
  Stopping containers &amp;amp; removing network
&lt;/h3&gt;

&lt;p&gt;Once you are done with you testing you can remove container with the help of below command, where you run docker stop command by passing container names to stop them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;stopping container&lt;br&gt;
&lt;code&gt;docker stop node-chrome node-edge node-firefox selenium-hub&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;removing docker network&lt;br&gt;
&lt;code&gt;docker network rm grid&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>automation</category>
      <category>docker</category>
      <category>selenium</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
