<?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: Utkarsh </title>
    <description>The latest articles on DEV Community by Utkarsh  (@utkarsh630).</description>
    <link>https://dev.to/utkarsh630</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%2F2621038%2Fb682c1e6-e940-454f-884a-9979b4950264.jpg</url>
      <title>DEV Community: Utkarsh </title>
      <link>https://dev.to/utkarsh630</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/utkarsh630"/>
    <language>en</language>
    <item>
      <title>🚀 APIs Made Simple: The Secret Language of the Web</title>
      <dc:creator>Utkarsh </dc:creator>
      <pubDate>Thu, 05 Feb 2026 17:58:00 +0000</pubDate>
      <link>https://dev.to/utkarsh630/apis-made-simple-the-secret-language-of-the-web-18nk</link>
      <guid>https://dev.to/utkarsh630/apis-made-simple-the-secret-language-of-the-web-18nk</guid>
      <description>&lt;h2&gt;
  
  
  🚀 APIs Made Simple: The Secret Language of the Web
&lt;/h2&gt;

&lt;p&gt;Have you ever received a &lt;strong&gt;404 Not Found&lt;/strong&gt; or a &lt;strong&gt;500 Internal Server Error&lt;/strong&gt; and wondered what the server was trying to tell you?&lt;/p&gt;

&lt;p&gt;In reality, APIs are not mysterious at all. Every API call is a &lt;strong&gt;simple two-way conversation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;client&lt;/strong&gt; asks the server to do something&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;server&lt;/strong&gt; replies with a status code explaining what happened&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you understand this conversation, APIs become much easier to debug, test, and design.&lt;/p&gt;

&lt;p&gt;To understand APIs clearly, you only need to focus on &lt;strong&gt;two core ideas&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;HTTP Methods&lt;/strong&gt; – What action you are asking the server to perform&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP Status Codes&lt;/strong&gt; – How the server responds to that action&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s break both of these down in simple terms.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠 HTTP Methods – What You Are Asking the Server to Do
&lt;/h2&gt;

&lt;p&gt;HTTP methods describe the &lt;strong&gt;action&lt;/strong&gt; you want the server to take.&lt;br&gt;
Think of them as &lt;strong&gt;verbs&lt;/strong&gt; in a sentence.&lt;/p&gt;




&lt;h3&gt;
  
  
  📖 GET – “Fetch the data”
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Used for &lt;strong&gt;reading data only&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Does &lt;strong&gt;not change&lt;/strong&gt; anything on the server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
Fetching an employee profile from an HR system or viewing product details in an app.&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;GET&lt;/strong&gt; when you only want information.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✍️ POST – “Create something new”
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Used to &lt;strong&gt;send data&lt;/strong&gt; to the server&lt;/li&gt;
&lt;li&gt;Creates a &lt;strong&gt;new resource&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
User registration, submitting a form, or placing a new e-commerce order.&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;POST&lt;/strong&gt; when something new needs to be created.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔁 PUT – “Replace the whole thing”
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Used to &lt;strong&gt;update an existing resource completely&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You send the &lt;strong&gt;entire object&lt;/strong&gt;, not just the changed fields&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
Replacing a full user profile including name, email, and address.&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;PUT&lt;/strong&gt; when you want to overwrite the existing data.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✂️ PATCH – “Update just a piece”
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Used for &lt;strong&gt;partial updates&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Only the fields that need to change are sent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
Updating only a user’s email address without sending the full profile.&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;PATCH&lt;/strong&gt; for small, targeted updates.&lt;/p&gt;




&lt;h3&gt;
  
  
  ❌ DELETE – “Remove it”
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Used to &lt;strong&gt;delete a specific resource&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
Removing a cart item or deleting a user account.&lt;/p&gt;




&lt;h3&gt;
  
  
  🩺 HEAD &amp;amp; OPTIONS – “The Check-Up”
&lt;/h3&gt;

&lt;p&gt;These methods are not about data changes but &lt;strong&gt;validation and safety&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HEAD&lt;/strong&gt;: Fetches headers only (no response body)
Useful for &lt;strong&gt;health checks&lt;/strong&gt; and performance testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OPTIONS&lt;/strong&gt;: Shows which HTTP methods are allowed
Essential for &lt;strong&gt;CORS and browser security checks&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔄 The Concept of Idempotency (Why It Matters)
&lt;/h2&gt;

&lt;p&gt;In API terms, &lt;strong&gt;idempotency&lt;/strong&gt; means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Repeating the same request multiple times gives the same result.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Idempotent Methods
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GET&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PUT&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DELETE&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HEAD&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OPTIONS&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
Deleting the same user twice still results in the user being deleted — nothing new happens.&lt;/p&gt;

&lt;h3&gt;
  
  
  Non-Idempotent Methods
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;POST&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PATCH&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
Sending the same POST request multiple times may create &lt;strong&gt;duplicate records&lt;/strong&gt; (such as multiple identical orders).&lt;/p&gt;

&lt;p&gt;Understanding idempotency is important for &lt;strong&gt;retries, error handling, and automation testing&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  📬 HTTP Status Codes – How the Server Replies
&lt;/h2&gt;

&lt;p&gt;After processing a request, the server responds with a &lt;strong&gt;status code&lt;/strong&gt; that explains the outcome.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ 2xx – Success (The Green Light)
&lt;/h3&gt;

&lt;p&gt;These codes mean the request was successful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;200 OK&lt;/strong&gt; – Request succeeded and data was returned&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;201 Created&lt;/strong&gt; – A new resource was created successfully&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;204 No Content&lt;/strong&gt; – The action worked, but there is no data to return (common for DELETE)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔁 3xx – Redirection (The Detour)
&lt;/h3&gt;

&lt;p&gt;These codes indicate the resource is located elsewhere or cached.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;301 Moved Permanently&lt;/strong&gt; – Used during API version changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;304 Not Modified&lt;/strong&gt; – Cached data is still valid, improving performance&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  ⚠️ 4xx – Client Errors (Check Your Request)
&lt;/h3&gt;

&lt;p&gt;These mean the &lt;strong&gt;client sent something wrong&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;400 Bad Request&lt;/strong&gt; – Invalid data or malformed request&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;401 Unauthorized&lt;/strong&gt; – Authentication failed or missing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;403 Forbidden&lt;/strong&gt; – Authenticated, but not allowed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;429 Too Many Requests&lt;/strong&gt; – Rate limit exceeded&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔥 5xx – Server Errors (Server Failure)
&lt;/h3&gt;

&lt;p&gt;These indicate problems on the &lt;strong&gt;server side&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;500 Internal Server Error&lt;/strong&gt; – Unhandled exception or bug&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;502 / 504&lt;/strong&gt; – Communication failures or timeouts between services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These errors usually require &lt;strong&gt;developer or infrastructure fixes&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 The Golden Rule of API Testing
&lt;/h2&gt;

&lt;p&gt;Always &lt;strong&gt;validate the status code first&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is the &lt;strong&gt;primary contract&lt;/strong&gt; between the client and the server.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;2xx&lt;/strong&gt; → It worked&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4xx&lt;/strong&gt; → Fix the request&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5xx&lt;/strong&gt; → Server problem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you understand this flow, API debugging becomes logical problem-solving instead of guesswork.&lt;/p&gt;




&lt;h3&gt;
  
  
  Final Thought
&lt;/h3&gt;

&lt;p&gt;APIs don’t fail randomly — they &lt;strong&gt;explain exactly what happened&lt;/strong&gt;.&lt;br&gt;
Learning to read HTTP methods and status codes is the first step toward mastering backend systems, API testing, and modern software development.&lt;br&gt;
🚀&lt;/p&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>restapi</category>
      <category>testing</category>
    </item>
    <item>
      <title>Day 04 - 🧩 Building a Complete Selenium Java Framework - Base Class Refactoring &amp; TestNG Suite Integration</title>
      <dc:creator>Utkarsh </dc:creator>
      <pubDate>Wed, 04 Feb 2026 18:01:00 +0000</pubDate>
      <link>https://dev.to/utkarsh630/day-04-building-a-complete-selenium-java-framework-base-class-refactoring-testng-suite-2n7k</link>
      <guid>https://dev.to/utkarsh630/day-04-building-a-complete-selenium-java-framework-base-class-refactoring-testng-suite-2n7k</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Day 04 – Base Class Refactoring &amp;amp; TestNG Suite Integration&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;By &lt;strong&gt;Day 03&lt;/strong&gt;, we had a working Base Class that could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launch a browser&lt;/li&gt;
&lt;li&gt;Read configuration values&lt;/li&gt;
&lt;li&gt;Open the application&lt;/li&gt;
&lt;li&gt;Close the browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On &lt;strong&gt;Day 04&lt;/strong&gt;, we make this code &lt;strong&gt;production-ready&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Today is about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Refactoring&lt;/strong&gt; (cleaning and modularising code)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimising TestNG lifecycle usage&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Introducing TestNG XML&lt;/strong&gt; for suite-level execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the point where our framework starts to feel &lt;strong&gt;professional&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Why Refactoring Is Necessary
&lt;/h2&gt;

&lt;p&gt;As frameworks grow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One long method becomes hard to debug&lt;/li&gt;
&lt;li&gt;Changes in one place can break others&lt;/li&gt;
&lt;li&gt;Reusability drops&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refactoring helps us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Split responsibilities&lt;/li&gt;
&lt;li&gt;Improve readability&lt;/li&gt;
&lt;li&gt;Prepare for parallel execution later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Rule of thumb:&lt;br&gt;
&lt;strong&gt;Small methods, single responsibility.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1: Refactoring the Base Class (Modern Approach)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  🔧 Key Improvements from Day 03
&lt;/h3&gt;

&lt;p&gt;✔ Load configuration &lt;strong&gt;once per suite&lt;/strong&gt;&lt;br&gt;
✔ Separate browser launch and configuration&lt;br&gt;
✔ Avoid unnecessary static waits&lt;br&gt;
✔ Prepare for cross-browser and parallel execution&lt;/p&gt;


&lt;h2&gt;
  
  
  📁 Updated File Location
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/main/java
 └── com.orangehrm.base
     └── BaseClass.java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ✅ Refactored &lt;code&gt;BaseClass.java&lt;/code&gt; (Industry Standard)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.orangehrm.base&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.FileInputStream&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.Duration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Properties&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.openqa.selenium.WebDriver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.openqa.selenium.chrome.ChromeDriver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.openqa.selenium.edge.EdgeDriver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.openqa.selenium.firefox.FirefoxDriver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.testng.annotations.AfterMethod&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.testng.annotations.BeforeMethod&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.testng.annotations.BeforeSuite&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseClass&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Properties&lt;/span&gt; &lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;WebDriver&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Load configuration only once before suite execution&lt;/span&gt;
    &lt;span class="nd"&gt;@BeforeSuite&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loadConfig&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;prop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Properties&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="nc"&gt;FileInputStream&lt;/span&gt; &lt;span class="n"&gt;fis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileInputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user.dir"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"/src/main/resources/config.properties"&lt;/span&gt;
            &lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fis&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RuntimeException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to load config.properties"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Runs before every test method&lt;/span&gt;
    &lt;span class="nd"&gt;@BeforeMethod&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;launchBrowser&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;configureBrowser&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Browser initialization&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;launchBrowser&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"browser"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toLowerCase&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"chrome"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ChromeDriver&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Selenium Manager handles driver&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"firefox"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FirefoxDriver&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"edge"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EdgeDriver&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RuntimeException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unsupported browser: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Browser configuration&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;configureBrowser&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;manage&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;maximize&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;manage&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;timeouts&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;implicitlyWait&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parseInt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"implicit_wait"&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"url"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Runs after every test method&lt;/span&gt;
    &lt;span class="nd"&gt;@AfterMethod&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;tearDown&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;quit&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔍 Important Corrections &amp;amp; Best Practices
&lt;/h2&gt;
&lt;h3&gt;
  
  
  ❌ Why We Removed &lt;code&gt;LockSupport&lt;/code&gt; / Static Waits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Hard waits are &lt;strong&gt;not recommended&lt;/strong&gt; in modern frameworks&lt;/li&gt;
&lt;li&gt;They block execution unnecessarily&lt;/li&gt;
&lt;li&gt;We will rely on &lt;strong&gt;explicit waits&lt;/strong&gt; inside the Action Driver (Day 05)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Static waits should only be used for &lt;strong&gt;debugging&lt;/strong&gt;, not framework design.&lt;/p&gt;


&lt;h3&gt;
  
  
  ✅ Why &lt;code&gt;@BeforeSuite&lt;/code&gt; Is Used for Config
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Configuration data is &lt;strong&gt;global&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Loading it once improves performance&lt;/li&gt;
&lt;li&gt;Prevents repeated file I/O operations&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  ⚠ Why WebDriver Is NOT Static
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Static WebDriver breaks &lt;strong&gt;parallel execution&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Causes session conflicts&lt;/li&gt;
&lt;li&gt;Modern frameworks use &lt;strong&gt;instance-level drivers&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Parallel execution will be introduced later using &lt;strong&gt;ThreadLocal&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 2: Introducing TestNG XML (Suite Control Center)
&lt;/h2&gt;

&lt;p&gt;So far, we ran tests by right-clicking test classes.&lt;br&gt;
In real projects, this is &lt;strong&gt;never done&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead, we use &lt;strong&gt;TestNG XML&lt;/strong&gt; to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Group tests&lt;/li&gt;
&lt;li&gt;Control execution order&lt;/li&gt;
&lt;li&gt;Enable parallel runs&lt;/li&gt;
&lt;li&gt;Integrate with CI/CD&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  📄 Create &lt;code&gt;testng.xml&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Location (recommended):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/test/resources/testng.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🧾 &lt;code&gt;testng.xml&lt;/code&gt; (Clean &amp;amp; Correct)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;suite&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"OrangeHRM Automation Suite"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;test&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Smoke Tests"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;classes&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;class&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"com.orangehrm.tests.DummyTest"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/classes&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/test&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/suite&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Running Tests Using TestNG XML
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ▶ How to Run
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Right-click &lt;code&gt;testng.xml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Run As → TestNG Suite&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ Expected Flow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Config loads once&lt;/li&gt;
&lt;li&gt;Browser launches before each test&lt;/li&gt;
&lt;li&gt;Application opens&lt;/li&gt;
&lt;li&gt;Test executes&lt;/li&gt;
&lt;li&gt;Browser closes cleanly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is &lt;strong&gt;exactly how CI tools like Jenkins run tests&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Day 04 Summary
&lt;/h2&gt;

&lt;p&gt;Today, you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Refactored the Base Class for scalability&lt;/li&gt;
&lt;li&gt;Applied TestNG lifecycle correctly&lt;/li&gt;
&lt;li&gt;Introduced suite-based execution&lt;/li&gt;
&lt;li&gt;Prepared the framework for future growth&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your framework is no longer “basic automation” —&lt;br&gt;
it is now &lt;strong&gt;architected&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Day 04 Task
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Refactor your &lt;code&gt;BaseClass&lt;/code&gt; as shown&lt;/li&gt;
&lt;li&gt;Create &lt;code&gt;testng.xml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;DummyTest&lt;/code&gt; to the suite&lt;/li&gt;
&lt;li&gt;Run tests using &lt;strong&gt;TestNG Suite&lt;/strong&gt;, not individual classes&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🚀 What’s Coming Next (Day 05)
&lt;/h2&gt;

&lt;p&gt;Next, we will build the &lt;strong&gt;Action Driver&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;click()&lt;/li&gt;
&lt;li&gt;sendKeys()&lt;/li&gt;
&lt;li&gt;explicit waits&lt;/li&gt;
&lt;li&gt;element visibility handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This will make test scripts:&lt;br&gt;
✔ Smaller&lt;br&gt;
✔ Cleaner&lt;br&gt;
✔ Easier to read&lt;/p&gt;

&lt;p&gt;You’ve officially crossed into &lt;strong&gt;framework engineering&lt;/strong&gt; territory 👏&lt;/p&gt;

</description>
      <category>selenium</category>
      <category>java</category>
      <category>tutorial</category>
      <category>automation</category>
    </item>
    <item>
      <title>Day 03 - Building a Complete Selenium Java Framework - The Backbone: Base Class and Configuration</title>
      <dc:creator>Utkarsh </dc:creator>
      <pubDate>Tue, 03 Feb 2026 17:56:00 +0000</pubDate>
      <link>https://dev.to/utkarsh630/day-03-building-a-complete-selenium-java-framework-the-backbone-base-class-and-configuration-2m6m</link>
      <guid>https://dev.to/utkarsh630/day-03-building-a-complete-selenium-java-framework-the-backbone-base-class-and-configuration-2m6m</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Day 03 – The Backbone: Base Class and Configuration&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;On &lt;strong&gt;Day 01&lt;/strong&gt;, we planned the framework.&lt;br&gt;
On &lt;strong&gt;Day 02&lt;/strong&gt;, we created the project and structure.&lt;/p&gt;

&lt;p&gt;Now on &lt;strong&gt;Day 03&lt;/strong&gt;, we build the &lt;strong&gt;most important part of the framework&lt;/strong&gt;—the &lt;strong&gt;Base Class&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If this framework were a building, the Base Class would be the &lt;strong&gt;foundation&lt;/strong&gt;.&lt;br&gt;
Every test we write later will stand on top of it.&lt;/p&gt;


&lt;h2&gt;
  
  
  🎯 Why Do We Need a Base Class?
&lt;/h2&gt;

&lt;p&gt;In automation testing, almost every test does the same starting work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launch the browser&lt;/li&gt;
&lt;li&gt;Navigate to the application URL&lt;/li&gt;
&lt;li&gt;Apply waits&lt;/li&gt;
&lt;li&gt;Close the browser after execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we write this logic &lt;strong&gt;inside every test&lt;/strong&gt;, our code becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repetitive&lt;/li&gt;
&lt;li&gt;Hard to maintain&lt;/li&gt;
&lt;li&gt;Error-prone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;Base Class&lt;/strong&gt; solves this problem by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Centralising browser setup and teardown&lt;/li&gt;
&lt;li&gt;Loading configuration values&lt;/li&gt;
&lt;li&gt;Ensuring all tests behave consistently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every test class will simply &lt;strong&gt;extend the Base Class&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1: Understanding &lt;code&gt;config.properties&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Hard-coding values like browser name or URL inside Java code is a bad practice.&lt;/p&gt;

&lt;p&gt;Instead, we use a &lt;strong&gt;configuration file&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to change&lt;/li&gt;
&lt;li&gt;No recompilation needed&lt;/li&gt;
&lt;li&gt;Supports multiple environments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  📄 &lt;code&gt;config.properties&lt;/code&gt; (Initial Version)
&lt;/h3&gt;

&lt;p&gt;This file lives inside:&lt;br&gt;
&lt;code&gt;src/main/resources/config.properties&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# Application Settings
&lt;/span&gt;&lt;span class="py"&gt;url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;https://opensource-demo.orangehrmlive.com/&lt;/span&gt;
&lt;span class="py"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;chrome&lt;/span&gt;
&lt;span class="py"&gt;implicit_wait&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔍 What Each Property Means
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;url&lt;/strong&gt; → Application under test&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;browser&lt;/strong&gt; → Which browser to launch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;implicit_wait&lt;/strong&gt; → Global wait time for element search&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Later, we’ll add more values as the framework grows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Creating the Base Class
&lt;/h2&gt;

&lt;p&gt;Now we write the &lt;strong&gt;Base Class&lt;/strong&gt;, which will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load the configuration file&lt;/li&gt;
&lt;li&gt;Launch the browser&lt;/li&gt;
&lt;li&gt;Apply waits&lt;/li&gt;
&lt;li&gt;Navigate to the application&lt;/li&gt;
&lt;li&gt;Close the browser after execution&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  📁 File Location
&lt;/h3&gt;

&lt;p&gt;Create the file here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/main/java
 └── com.orangehrm.base
     └── BaseClass.java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🧩 BaseClass.java – Complete Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.orangehrm.base&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.FileInputStream&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Properties&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.Duration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.openqa.selenium.WebDriver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.openqa.selenium.chrome.ChromeDriver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.openqa.selenium.firefox.FirefoxDriver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.openqa.selenium.edge.EdgeDriver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.testng.annotations.AfterMethod&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.testng.annotations.BeforeMethod&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseClass&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Properties&lt;/span&gt; &lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;WebDriver&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Load configuration from config.properties&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loadConfig&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;prop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Properties&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="nc"&gt;FileInputStream&lt;/span&gt; &lt;span class="n"&gt;fis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileInputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user.dir"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"/src/main/resources/config.properties"&lt;/span&gt;
            &lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fis&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@BeforeMethod&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;loadConfig&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;browserName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"browser"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Browser selection&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;browserName&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"chrome"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ChromeDriver&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;browserName&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"firefox"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FirefoxDriver&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;browserName&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"edge"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EdgeDriver&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Browser management&lt;/span&gt;
        &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;manage&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;maximize&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;manage&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;timeouts&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;implicitlyWait&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parseInt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"implicit_wait"&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Launch application&lt;/span&gt;
        &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"url"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@AfterMethod&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;tearDown&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;quit&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Important Concepts You Used Today
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔹 Selenium Manager (Selenium 4)
&lt;/h3&gt;

&lt;p&gt;You’ll notice we &lt;strong&gt;did not use&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"webdriver.chrome.driver"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Selenium 4 introduces &lt;strong&gt;Selenium Manager&lt;/strong&gt;, which:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically downloads drivers&lt;/li&gt;
&lt;li&gt;Manages driver paths internally&lt;/li&gt;
&lt;li&gt;Reduces setup headaches&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔹 Implicit Wait
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Applied globally for the entire session&lt;/li&gt;
&lt;li&gt;Selenium waits up to the defined time before throwing &lt;code&gt;NoSuchElementException&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;manage&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;timeouts&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;implicitlyWait&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🔹 Access Modifiers
&lt;/h3&gt;

&lt;p&gt;We used &lt;strong&gt;&lt;code&gt;protected&lt;/code&gt;&lt;/strong&gt; for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;WebDriver&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Properties&lt;/span&gt; &lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Child classes (test classes) can access them&lt;/li&gt;
&lt;li&gt;Still protected from outside misuse&lt;/li&gt;
&lt;/ul&gt;




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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;@BeforeMethod&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Runs before &lt;strong&gt;every test method&lt;/strong&gt;&lt;br&gt;
→ Browser always starts fresh&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;@AfterMethod&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Runs after &lt;strong&gt;every test method&lt;/strong&gt;&lt;br&gt;
→ Browser always closes cleanly&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guarantees &lt;strong&gt;test isolation&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Validating the Backbone (Very Important)
&lt;/h2&gt;

&lt;p&gt;Before moving forward, we must confirm:&lt;br&gt;
👉 The Base Class actually works.&lt;/p&gt;


&lt;h3&gt;
  
  
  🧪 Create a Dummy Test
&lt;/h3&gt;

&lt;p&gt;Create this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/test/java
 └── DummyTest.java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.testng.annotations.Test&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.orangehrm.base.BaseClass&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DummyTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseClass&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testBaseSetup&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// No code needed&lt;/span&gt;
        &lt;span class="c1"&gt;// Browser should open and close automatically&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ✅ Expected Behaviour
&lt;/h3&gt;

&lt;p&gt;When you run this test:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Browser opens&lt;/li&gt;
&lt;li&gt;Navigates to Orange HRM login page&lt;/li&gt;
&lt;li&gt;Maximises window&lt;/li&gt;
&lt;li&gt;Waits applied&lt;/li&gt;
&lt;li&gt;Browser closes after execution&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If this happens → &lt;strong&gt;Day 03 is successful&lt;/strong&gt; 🎉&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Day 03 Summary
&lt;/h2&gt;

&lt;p&gt;Today, you built:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;centralised Base Class&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configuration-driven browser setup&lt;/li&gt;
&lt;li&gt;Clean startup and shutdown logic&lt;/li&gt;
&lt;li&gt;Selenium 4-ready WebDriver initialization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This Base Class will be reused by &lt;strong&gt;every test&lt;/strong&gt; going forward.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 What’s Next?
&lt;/h2&gt;

&lt;p&gt;On &lt;strong&gt;Day 04&lt;/strong&gt;, we will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the &lt;strong&gt;Action Driver&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Centralise reusable actions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;click&lt;/li&gt;
&lt;li&gt;sendKeys&lt;/li&gt;
&lt;li&gt;waits&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This will make test scripts &lt;strong&gt;short, clean, and readable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You’ve just completed the &lt;strong&gt;core backbone&lt;/strong&gt; of the framework 💪&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>automation</category>
      <category>selenium</category>
      <category>java</category>
    </item>
    <item>
      <title>🛠️ Day 02 - Building a Complete Selenium Java Framework – Project Initiation and Structure</title>
      <dc:creator>Utkarsh </dc:creator>
      <pubDate>Mon, 02 Feb 2026 17:48:00 +0000</pubDate>
      <link>https://dev.to/utkarsh630/day-02-building-a-complete-selenium-java-framework-project-initiation-and-structure-4dmj</link>
      <guid>https://dev.to/utkarsh630/day-02-building-a-complete-selenium-java-framework-project-initiation-and-structure-4dmj</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Day 02 – Project Initiation and Structure&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;On &lt;strong&gt;Day 01&lt;/strong&gt;, we designed the blueprint of our Selenium Java framework.&lt;br&gt;
On &lt;strong&gt;Day 02&lt;/strong&gt;, we finally move from &lt;strong&gt;planning to action&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Today is about setting up the &lt;strong&gt;foundation of the project&lt;/strong&gt;—the part you build once and rely on throughout the framework’s lifetime. If this step is done correctly, everything that comes later becomes easier, cleaner, and more scalable.&lt;/p&gt;


&lt;h2&gt;
  
  
  🎯 What We Will Do Today
&lt;/h2&gt;

&lt;p&gt;By the end of Day 02, you will have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;Maven-based Selenium project&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;All &lt;strong&gt;required dependencies&lt;/strong&gt; configured&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;clean, industry-standard folder structure&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;central configuration file&lt;/strong&gt; for global settings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup works the same way in &lt;strong&gt;real-world automation projects&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1: Creating the Maven Project
&lt;/h2&gt;

&lt;p&gt;We use &lt;strong&gt;Maven&lt;/strong&gt; because it automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Downloads required libraries&lt;/li&gt;
&lt;li&gt;Manages versions&lt;/li&gt;
&lt;li&gt;Integrates easily with CI/CD tools like Jenkins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can use &lt;strong&gt;Eclipse&lt;/strong&gt; or &lt;strong&gt;IntelliJ IDEA&lt;/strong&gt;—both are widely used.&lt;/p&gt;


&lt;h3&gt;
  
  
  ▶ Option 1: Create Maven Project in Eclipse
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Eclipse IDE&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;File → New → Maven Project&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Next&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Archetype: &lt;code&gt;maven-archetype-quickstart&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Version: &lt;strong&gt;1.4 or 1.5&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Next&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Group Id:&lt;/strong&gt; &lt;code&gt;com.orangehrm&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Artifact Id:&lt;/strong&gt; &lt;code&gt;OrangeHRM_Project&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Finish the setup&lt;/li&gt;
&lt;li&gt;Ensure the project is using &lt;strong&gt;Java 17&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Right-click project → Properties → Java Compiler → Set to &lt;strong&gt;17&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eclipse will create a basic Maven project with a &lt;code&gt;pom.xml&lt;/code&gt; file.&lt;/p&gt;


&lt;h3&gt;
  
  
  ▶ Option 2: Create Maven Project in IntelliJ IDEA
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;IntelliJ IDEA&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;New Project&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Maven&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Next&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GroupId:&lt;/strong&gt; &lt;code&gt;com.orangehrm&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ArtifactId:&lt;/strong&gt; &lt;code&gt;OrangeHRM_Project&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;JDK 17&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Finish&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;IntelliJ will automatically download Maven dependencies in the background.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 2: Configuring Dependencies (pom.xml)
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;pom.xml&lt;/code&gt; file is the &lt;strong&gt;heart of a Maven project&lt;/strong&gt;.&lt;br&gt;
This is where we define all external libraries our framework needs.&lt;/p&gt;

&lt;p&gt;For now, we add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Selenium WebDriver&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TestNG&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  📌 Why these?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Selenium&lt;/strong&gt; → Browser automation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TestNG&lt;/strong&gt; → Test execution, grouping, reporting, and parallel runs&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  🔧 pom.xml – Essential Dependencies
&lt;/h3&gt;

&lt;p&gt;Add the following inside the &lt;code&gt;&amp;lt;dependencies&amp;gt;&lt;/code&gt; section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Selenium WebDriver --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.seleniumhq.selenium&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;selenium-java&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;4.27.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- TestNG Framework --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.testng&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;testng&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;7.10.2&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;compile&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once saved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eclipse → Right-click project → &lt;strong&gt;Maven → Update Project&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;IntelliJ → Maven reload happens automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If there are no errors, your dependencies are set correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Designing the Folder Structure
&lt;/h2&gt;

&lt;p&gt;The default Maven structure is good, but not enough for a &lt;strong&gt;scalable automation framework&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We now create a &lt;strong&gt;clean, logical package hierarchy&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  🚨 First Step
&lt;/h3&gt;

&lt;p&gt;Delete any &lt;strong&gt;default packages&lt;/strong&gt; created under:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/main/java&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/test/java&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ll build our own structure.&lt;/p&gt;




&lt;h3&gt;
  
  
  📁 Packages Under &lt;code&gt;src/main/java&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Create the following packages:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;com.orangehrm.base&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Browser setup and teardown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;com.orangehrm.actiondriver&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Common Selenium actions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;com.orangehrm.pages&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Page Object classes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;com.orangehrm.utilities&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Excel, reporting, helpers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;com.orangehrm.listeners&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TestNG listeners&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This separation ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clean code&lt;/li&gt;
&lt;li&gt;Easy maintenance&lt;/li&gt;
&lt;li&gt;Better scalability&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  📁 Resources Folder Setup
&lt;/h3&gt;

&lt;p&gt;Under &lt;strong&gt;&lt;code&gt;src/main/resources&lt;/code&gt;&lt;/strong&gt;, create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;config.properties&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;log4j2.xml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will use these files throughout the framework.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Global Configuration Using config.properties
&lt;/h2&gt;

&lt;p&gt;Hardcoding values like URLs and browsers is a &lt;strong&gt;bad practice&lt;/strong&gt;.&lt;br&gt;
Instead, we store them in a &lt;strong&gt;configuration file&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This makes switching environments easy (QA, UAT, Production).&lt;/p&gt;


&lt;h3&gt;
  
  
  📝 config.properties – Initial Setup
&lt;/h3&gt;

&lt;p&gt;Create this file in &lt;code&gt;src/main/resources&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# Application Settings
&lt;/span&gt;&lt;span class="py"&gt;url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;https://opensource-demo.orangehrmlive.com/&lt;/span&gt;
&lt;span class="py"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;chrome&lt;/span&gt;

&lt;span class="c"&gt;# Timeout Settings
&lt;/span&gt;&lt;span class="py"&gt;implicit_wait&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10&lt;/span&gt;
&lt;span class="py"&gt;explicit_wait&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;30&lt;/span&gt;

&lt;span class="c"&gt;# Test Credentials
&lt;/span&gt;&lt;span class="py"&gt;username&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;
&lt;span class="py"&gt;password&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;admin123&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Later, our framework will &lt;strong&gt;read these values dynamically&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Day 02 Summary
&lt;/h2&gt;

&lt;p&gt;By the end of today, you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;Maven-based Selenium project&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selenium and TestNG fully configured&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;professional folder structure&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;central configuration system&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the &lt;strong&gt;backbone&lt;/strong&gt; of the automation framework.&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Day 02 Task
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create the Maven project (Eclipse or IntelliJ)&lt;/li&gt;
&lt;li&gt;Add Selenium and TestNG dependencies&lt;/li&gt;
&lt;li&gt;Create all required packages&lt;/li&gt;
&lt;li&gt;Validate the setup:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Maven dependencies resolve successfully&lt;/li&gt;
&lt;li&gt;No build errors&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 What’s Next?
&lt;/h2&gt;

&lt;p&gt;On &lt;strong&gt;Day 03&lt;/strong&gt;, we will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the &lt;strong&gt;Base Class&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configure WebDriver using &lt;strong&gt;Selenium Manager&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Launch the browser dynamically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real automation begins next 🚦&lt;/p&gt;

</description>
      <category>selenium</category>
      <category>testing</category>
      <category>tutorial</category>
      <category>automation</category>
    </item>
    <item>
      <title>🚗 Day 01: Building a Selenium Java Framework — The Blueprint</title>
      <dc:creator>Utkarsh </dc:creator>
      <pubDate>Sun, 01 Feb 2026 17:35:51 +0000</pubDate>
      <link>https://dev.to/utkarsh630/day-01-building-a-selenium-java-framework-the-blueprint-5fj9</link>
      <guid>https://dev.to/utkarsh630/day-01-building-a-selenium-java-framework-the-blueprint-5fj9</guid>
      <description>&lt;h2&gt;
  
  
  A Small Story to Begin…
&lt;/h2&gt;

&lt;p&gt;Imagine you’re about to build a &lt;strong&gt;race car&lt;/strong&gt;, not a toy one, but a real machine that must run fast, safely, and reliably on different tracks.&lt;br&gt;
You wouldn’t just start welding parts together randomly, right?&lt;/p&gt;

&lt;p&gt;First, you’d:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decide the &lt;strong&gt;design&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Choose the &lt;strong&gt;engine&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Pick the &lt;strong&gt;tools&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Set up the &lt;strong&gt;garage&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s exactly what we’re doing on &lt;strong&gt;Day 01&lt;/strong&gt; of building a &lt;strong&gt;Selenium Automation Framework&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Today is all about &lt;strong&gt;planning and preparation&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 What Is an Automation Framework?
&lt;/h2&gt;

&lt;p&gt;An automation framework is like a &lt;strong&gt;rulebook and toolbox combined&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of writing messy test scripts again and again, a framework:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tells you &lt;strong&gt;how to write code&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Decides &lt;strong&gt;where things should live&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Manages &lt;strong&gt;test data&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Keeps tests &lt;strong&gt;easy to reuse and easy to fix&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 The result?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Less duplicate work&lt;/li&gt;
&lt;li&gt;Easier maintenance&lt;/li&gt;
&lt;li&gt;Tests that work on different systems&lt;/li&gt;
&lt;li&gt;Happy testers 😄&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧰 Our Toolbelt (Technology Stack)
&lt;/h2&gt;

&lt;p&gt;To build a strong and modern framework, we’ll use trusted tools—just like choosing good materials for a house.&lt;/p&gt;

&lt;p&gt;Here’s what we’re working with:&lt;/p&gt;

&lt;h3&gt;
  
  
  🔹 Core Engine
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Selenium WebDriver 4&lt;/strong&gt; – the heart of browser automation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔹 Language &amp;amp; IDE
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Java 17&lt;/strong&gt; – our programming language&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eclipse/ IntelliJ IDE&lt;/strong&gt; – where we write and run code&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔹 Build Tool
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Maven&lt;/strong&gt; – manages libraries and dependencies automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔹 Testing Framework
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TestNG&lt;/strong&gt; – organizes tests, controls execution, and handles reports&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔹 Reporting
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extent Spark Reports&lt;/strong&gt; – beautiful, visual test reports&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔹 Version Control
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Git &amp;amp; GitHub&lt;/strong&gt; – track code changes and collaborate like pros&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔹 CI/CD &amp;amp; Containers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Jenkins&lt;/strong&gt; – automate test execution&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt; – run tests inside containers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don’t worry if some of these sound new—we’ll meet them properly later.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌟 What Makes This Framework Special?
&lt;/h2&gt;

&lt;p&gt;This isn’t a “hello world” framework. It’s designed for &lt;strong&gt;real-world projects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Some cool features we’ll build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🚀 &lt;strong&gt;Selenium Manager&lt;/strong&gt; – no need to manually download drivers&lt;/li&gt;
&lt;li&gt;📸 &lt;strong&gt;Screenshots in Base64 format&lt;/strong&gt; – directly embedded in reports&lt;/li&gt;
&lt;li&gt;🖍️ &lt;strong&gt;Element highlighting&lt;/strong&gt; – elements get a border when tests fail&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;Parallel execution&lt;/strong&gt; – run tests faster&lt;/li&gt;
&lt;li&gt;🌍 &lt;strong&gt;Cross-browser testing&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🔗 &lt;strong&gt;API and Database testing support&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Basically, this framework is ready for &lt;strong&gt;industry-level automation&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ Framework Structure (The Building Blocks)
&lt;/h2&gt;

&lt;p&gt;Think of the framework like a well-organized office.&lt;/p&gt;

&lt;h3&gt;
  
  
  1️⃣ Base Class
&lt;/h3&gt;

&lt;p&gt;This is the &lt;strong&gt;foundation&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opens the browser&lt;/li&gt;
&lt;li&gt;Closes the browser&lt;/li&gt;
&lt;li&gt;Handles setup and teardown&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2️⃣ Action Driver Class
&lt;/h3&gt;

&lt;p&gt;This is your &lt;strong&gt;helper&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clicks elements&lt;/li&gt;
&lt;li&gt;Types text&lt;/li&gt;
&lt;li&gt;Waits for elements
Reusable methods live here.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3️⃣ Page Classes (POM)
&lt;/h3&gt;

&lt;p&gt;Each web page gets its own class.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login page&lt;/li&gt;
&lt;li&gt;Dashboard page&lt;/li&gt;
&lt;li&gt;Employee page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This follows the &lt;strong&gt;Page Object Model&lt;/strong&gt;, which keeps tests clean and readable.&lt;/p&gt;

&lt;h3&gt;
  
  
  4️⃣ Utility Classes
&lt;/h3&gt;

&lt;p&gt;These handle the behind-the-scenes work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading data from Excel&lt;/li&gt;
&lt;li&gt;Database connections&lt;/li&gt;
&lt;li&gt;Report configuration&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📂 Project Folder Structure
&lt;/h2&gt;

&lt;p&gt;We’ll follow a professional layout:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;src/main/java&lt;/strong&gt;&lt;br&gt;
👉 Base classes, page objects, utilities&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;src/test/java&lt;/strong&gt;&lt;br&gt;
👉 Actual test cases and validations&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation keeps logic and tests nicely organized.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Day 01 Task: Get Your Environment Ready
&lt;/h2&gt;

&lt;p&gt;Before driving the car, we prepare the road.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔍 What You Should Already Know
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Basic Java (variables, data types, operators)&lt;/li&gt;
&lt;li&gt;Selenium WebDriver basics&lt;/li&gt;
&lt;li&gt;TestNG annotations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📝 Today’s Checklist
&lt;/h3&gt;

&lt;p&gt;Install and verify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;☑️ &lt;strong&gt;Java&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;☑️ &lt;strong&gt;Eclipse IDE/ IntelliJ&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;☑️ &lt;strong&gt;Maven&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once these are ready, your system becomes our &lt;strong&gt;automation garage&lt;/strong&gt; 🛠️&lt;/p&gt;




&lt;h2&gt;
  
  
  🚦 What’s Next?
&lt;/h2&gt;

&lt;p&gt;The next day:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We’ll create the &lt;strong&gt;Maven project&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Set up &lt;strong&gt;pom.xml&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Start automating real test cases on the &lt;strong&gt;Orange HRM application&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For now, relax—you’ve completed &lt;strong&gt;Day 01: The Blueprint&lt;/strong&gt; 🎉&lt;br&gt;
The journey has officially begun.&lt;/p&gt;

</description>
      <category>selenium</category>
      <category>testing</category>
      <category>tutorial</category>
      <category>automation</category>
    </item>
    <item>
      <title>API Testing: A Beginner’s Guide</title>
      <dc:creator>Utkarsh </dc:creator>
      <pubDate>Wed, 19 Feb 2025 19:26:03 +0000</pubDate>
      <link>https://dev.to/utkarsh630/api-testing-a-beginners-guide-1mn5</link>
      <guid>https://dev.to/utkarsh630/api-testing-a-beginners-guide-1mn5</guid>
      <description>&lt;p&gt;APIs (Application Programming Interfaces) are the backbone of modern software, enabling apps to communicate and share data. Thus API Testing ensures that these interactions can occur when expected. This beginner-friendly guide gives an overview of API testing, its importance, types, tools, and best practices.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What is API Testing?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;API testing is a sort of software testing to check an application programming interface (API) against functional, reliability, performance, and security parameters. Unlike UI testing, which focuses on the front end, API testing checks the business logic relevant to data response and communication between various software components.  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Importance of API Testing&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Guarantees data integrity and seamless intercommunication between systems
&lt;/li&gt;
&lt;li&gt;Spells vulnerability to security before time
&lt;/li&gt;
&lt;li&gt;Aids in faster releases with automation integration
&lt;/li&gt;
&lt;li&gt;Reduces UI dependency while accelerating the whole process of testing and increasing efficiency
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Types of API Testing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;API Testing can be divided into further types, including:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Functional Testing&lt;/strong&gt;: Verifying input and output whether the API works as intended.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Testing&lt;/strong&gt;: The tests API under different loads for speed, responsiveness, and stability.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load Testing&lt;/strong&gt;: Checks whether the API responds or not against heavy requests.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Testing&lt;/strong&gt;: Testing for vulnerabilities such as unauthorized access, data breaches, and injection attacks.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration Testing&lt;/strong&gt;: Verifying the performance of APIs in collaboration with other services or applications.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Negative Testing&lt;/strong&gt;: Verifying how the API responds to inputs that are invalid or unexpected.
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;How API Testing Works&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;API testing consists of dispatching requests to an API endpoint and validating the responses. A basic workflow consists of the following activities:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;API Documentation Understanding&lt;/strong&gt;: An overview of available endpoints, request methods (GET, POST, PUT, DELETE), parameters, and authentication procedures.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test Case Setup&lt;/strong&gt;: Input data, expected output, and validation criterion established.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sending API Requests&lt;/strong&gt;: Tools used may include Postman, Curl, or automated scripts.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response Validation&lt;/strong&gt;: Status codes (200 OK, 404 Not Found, etc.), response times, and returned data.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Tests Automation&lt;/strong&gt;: Implementing automation by means of Rest Assured/Postman/Karate, etc.
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Common API Testing Tools&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The list below names some popular API testing tools:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Postman&lt;/strong&gt;: A user-friendly tool for manual and automated API testing.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rest Assured&lt;/strong&gt;: Java library for API automation.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SoapUI&lt;/strong&gt;: Best for SOAP and REST API testing.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Karate&lt;/strong&gt;: Combines API testing, UI automation, and performance testing.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JMeter&lt;/strong&gt;: Mainly for performance and load testing.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Best Practices for API Testing&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Read the API documentation carefully&lt;/strong&gt; before preparing test cases.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the response status codes, headers, and data&lt;/strong&gt; against what is expected.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check for authentication mechanisms&lt;/strong&gt; (OAuth, API key, JWT, etc.) in place.
&lt;/li&gt;
&lt;li&gt;**Test various scenarios, with an emphasis on testing edge cases and negative inputs.
&lt;/li&gt;
&lt;li&gt;Build automation for any repetitive API tests** to save time and extend coverage.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API performance should be monitored&lt;/strong&gt; to meet the required SLA.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;API testing is central to guaranteeing seamless integration and functionality in the domain of modern applications. With an understanding of different types, tools, and best practices, you can efficiently carry out API testing and contribute to software quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s Next?
&lt;/h3&gt;

&lt;p&gt;💬 Got questions about API testing? Drop them in the comments!&lt;br&gt;
📌 What topic should we cover next? Let us know!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>tutorial</category>
      <category>api</category>
      <category>postman</category>
    </item>
    <item>
      <title>My First Steps with Playwright 🎭: A Tester’s Journey from Selenium</title>
      <dc:creator>Utkarsh </dc:creator>
      <pubDate>Wed, 01 Jan 2025 21:26:15 +0000</pubDate>
      <link>https://dev.to/utkarsh630/my-first-steps-with-playwright-a-testers-journey-from-selenium-4bj1</link>
      <guid>https://dev.to/utkarsh630/my-first-steps-with-playwright-a-testers-journey-from-selenium-4bj1</guid>
      <description>&lt;h3&gt;
  
  
  A Little About Me
&lt;/h3&gt;

&lt;p&gt;Hi! I’m &lt;code&gt;Utkarsh&lt;/code&gt;, a software tester and automation enthusiast who has experience with the software known as Selenium. I still remember the first time I discovered this gem of a tool – I was absolutely in awe that there was a tool that could automate browsers, manipulate user actions, and handle testing all at once. It was like finding a secret passage in a video game!🎮 &lt;/p&gt;

&lt;p&gt;Fast forward a couple of days and I came across Playwright, and since then I’ve been trying out this tool. I’m still working my way around it, but I’ve already discovered some incredible functionalities that provide terrific support to Playwright as a browser automation tool. Today, I’ll share with you what I’ve learned so far and guide you through my journey. So grab your coffee ☕️ and let’s dive in. &lt;br&gt;
Here's a glimpse of what we’ll be covering:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Auto-Waiting for Elements ⏳&lt;/li&gt;
&lt;li&gt;Speed and Performance ⚡️&lt;/li&gt;
&lt;li&gt;Handling Modern Web Interactions 🖱️&lt;/li&gt;
&lt;li&gt;Headless Mode 👻&lt;/li&gt;
&lt;li&gt;Simplicity &amp;amp; Reporting (Traces, Screenshots) 📸 - Aww, this one's a keeper!&lt;/li&gt;
&lt;/ol&gt;


&lt;h3&gt;
  
  
  My First Playwright Test: Automating Login Form
&lt;/h3&gt;

&lt;p&gt;Okay, so now let's just get down and dirty, for the first time let's touch code. My first trial with Playwright was simple: go to a site, fill out a login form, if something goes wrong, take a screenshot. You know, a classic "let's see if this stuff works" type of test. &lt;/p&gt;


&lt;h4&gt;
  
  
  Prerequisites:
&lt;/h4&gt;

&lt;p&gt;To get things flowing before the wand-waving magic starts, here is what you must have to get started: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install Node.js (obviously the engine behind everything)&lt;/li&gt;
&lt;li&gt;Install NPM (so your project can work)&lt;/li&gt;
&lt;li&gt;Install any editor (but I recommend Visual Studio Code for fact)&lt;/li&gt;
&lt;li&gt;Basic JavaScript Knowledge (or at least the ability to Google 
"what is a callback?")&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Setting Up the Project:
&lt;/h4&gt;

&lt;p&gt;Alright, let’s not waste time. You’ve installed Node.js and NPM on your machine? Okay fine-no outdated stuff around here, my friend! Now open your editor, create a new folder (or directory), and fire up the terminal in that folder.&lt;/p&gt;

&lt;p&gt;Next, here comes the magic: type in the command below.&lt;br&gt;
&lt;code&gt;npm init playwright&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Just that? Really? Yes, really! It is so simple that I feel like cheating. 😎 After you run this, Playwright will ask you few things: "What language are you comfortable with? JS or TypeScript?" and "Where should the test files go?" And, voila-yay! You’re done, now you are ready to roll! &lt;/p&gt;

&lt;p&gt;No more manual downloading dependencies, JAR files, and so on complicated things. One command and you are ready! 🎩✨&lt;/p&gt;

&lt;p&gt;On successful setup, your project structure should look somewhat like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fezp4gr0p4ipo86w0gmzg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fezp4gr0p4ipo86w0gmzg.png" alt="Workspace Project Structure" width="800" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the present moment, there's no need to keep worrying about all those file obligations; focus at the present with:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tests&lt;/code&gt; folder: This is where all your test files go. Simple.&lt;br&gt;
&lt;code&gt;playwright.config.js&lt;/code&gt; file: Now, this is where the magic happens. Seriously, the config file is like the control room of your automation spaceship. 🛸&lt;br&gt;
The config file lets you do a ton of stuff, like generating reports, taking screenshots, setting auto-wait for elements, switching between browsers, and much more. But, let’s keep it simple for now, just like I learned (and still learning) 😜. &lt;/p&gt;

&lt;p&gt;This is a really simple configuration for your config file under &lt;code&gt;module.exports&lt;/code&gt;. Just keep this and for now, comment out the rest of the code in the file (but please, don't touch the braces - they're sacred! Seriously, I've learned them the hard way. 😬).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = defineConfig({
  testDir: './tests',
  timeout: 30 * 1000,
  expect:{
    timeout:5000
  },
  reporter: 'html',
  use:{
    browserName: 'chromium',
    screenshot: 'only-on-failure',
    trace: 'retain-on-failure'
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can explore example files and run tests to get an idea of how things work. But now, let’s get to the fun part: writing some test cases!&lt;/p&gt;




&lt;h5&gt;
  
  
  Let’s Write a Test: Automating Login Form
&lt;/h5&gt;

&lt;p&gt;Here’s a simple test script that goes to the login page, enters credentials, clicks the login button, and hopefully logs you in (or breaks the page and takes a screenshot – whichever comes first 😉)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const {test, expect} = require('@playwright/test');
test.only('Login Test Case',async({page})=&amp;gt;{
    await page.goto('https://rahulshettyacademy.com/client');
    await page.locator('#userEmail').fill('rajusin675@gmail.com');
    await page.locator('#userPassword').fill('Abc@12345');
    await page.locator('#login').click();
});

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

&lt;/div&gt;



&lt;p&gt;Let me explain this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;const { test, expect } = require('@playwright/test')&lt;/code&gt; – This imports the test and expect functions, which are used to define and run your tests.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;test.only('Login Test Case', async ({ page }) =&amp;gt; {...})&lt;/code&gt; – This defines the test case. The &lt;code&gt;only&lt;/code&gt;(optional) method makes sure that this is the test that runs, and the async({page}) part tells Playwright that we're working with a browser page.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;await page.goto('https://rahulshettyacademy.com/client')&lt;/code&gt; – This navigates to the login page.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;await page.locator()&lt;/code&gt; - This locates the required field and &lt;code&gt;fill()&lt;/code&gt; method enter values into the field, just like findElement() and sendkeys() in selenium respectively.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;click()&lt;/code&gt; method does exactly what its name promises—it clicks on the element.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pretty simple, right? Just a few lines, and your automation test is ready to go. 💥&lt;/p&gt;

&lt;h4&gt;
  
  
  Running the Test: Headless vs. Headed Mode
&lt;/h4&gt;

&lt;p&gt;Now let’s run the test, and there are two modes you can try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Headless mode (no browser window shows up, it runs in the background):
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;npx playwright test&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Headed mode (browser window pops up, so you can watch the magic unfold):
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;npx playwright test --headed&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;And that’s it! You’ve just run your first automation test using Playwright. How cool is that? 🧑‍💻✨&lt;/p&gt;




&lt;h3&gt;
  
  
  Conclusion: Automation = Magic + Fun
&lt;/h3&gt;

&lt;p&gt;It is always a thrill to write the first automation script using Selenium, Playwright, or Cypress. There is something really satisfying when it sees your browser performs all your tasks for you. And of course, brag to everyone-including relatives-about your awesome coding skills and keeping that “tech guru” aura around your gang. You know the thing.😎&lt;br&gt;
So, go ahead, try it out, and feel free to share your experiences with me! Let’s continue to automate our way to a better world – one test at a time.🛠️🎉&lt;/p&gt;

</description>
      <category>playwright</category>
      <category>selenium</category>
      <category>testing</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
