<?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>Forem: Nael Marwan</title>
    <description>The latest articles on Forem by Nael Marwan (@naelabdeljawad).</description>
    <link>https://forem.com/naelabdeljawad</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%2F218245%2Fe2d602a7-f53c-4802-b3b4-20ecbf549744.jpeg</url>
      <title>Forem: Nael Marwan</title>
      <link>https://forem.com/naelabdeljawad</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/naelabdeljawad"/>
    <language>en</language>
    <item>
      <title>Navigating the Path to Success: Essential Advice for Junior Developers</title>
      <dc:creator>Nael Marwan</dc:creator>
      <pubDate>Fri, 01 Mar 2024 19:59:55 +0000</pubDate>
      <link>https://forem.com/naelabdeljawad/navigating-the-path-to-success-essential-advice-for-junior-developers-8ih</link>
      <guid>https://forem.com/naelabdeljawad/navigating-the-path-to-success-essential-advice-for-junior-developers-8ih</guid>
      <description>&lt;p&gt;Embarking on the journey of becoming a software developer is an exciting yet daunting endeavor, especially for junior developers still navigating the complexities of the tech industry. As students transitioning into the professional realm, the road ahead may seem uncertain, filled with opportunities and challenges alike. In this article, we aim to illuminate this path by offering invaluable advice tailored specifically for junior developers. From acing interviews to cultivating confidence and making informed decisions, these essential tips will serve as guiding beacons, empowering aspiring developers to embark on their careers with clarity and confidence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Essential Advice for Students and Juniors Pursuing Career Opportunities:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Conduct an Interview of Your Own: &lt;/strong&gt;&lt;br&gt;
Don't forget that interviews are a two-way street. While you're being evaluated, take the opportunity to assess the manager who will oversee your work. Is their management style compatible with your own working preferences and personality? Asking questions about the team dynamics, work culture, and expectations can help you gauge if the fit is right for you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Look Beyond GPA: &lt;/strong&gt;&lt;br&gt;
While your GPA may hold some weight in initial job applications, it's essential to recognize that real-world experience often outweighs academic performance in the long run. Many startups and smaller companies prioritize practical skills and problem-solving abilities over GPA, valuing candidates who can hit the ground running and contribute meaningfully to their teams. &lt;br&gt;
Moreover, as you gain experience in your first position, your GPA becomes less relevant in the eyes of potential employers. Once you've accumulated relevant experience and proven your capabilities in a professional setting, future job opportunities will likely focus more on your practical skills, accomplishments, and industry knowledge rather than your academic record. &lt;br&gt;
This means that if you're passionate about working for a particular company or in a specific industry, don't be discouraged if your GPA isn't perfect. Focus on gaining valuable experience in your field, honing your technical skills, and building a strong professional network. As you grow in your career, opportunities to transition to your dream company will arise, and your GPA will become a minor detail in comparison to your demonstrated expertise and achievements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Evaluate Startup vs. Corporate Culture: &lt;/strong&gt;&lt;br&gt;
Consider the trade-offs between working in a startup versus a large corporation. Startups offer exposure to a variety of tasks and technologies, providing valuable hands-on experience. However, be prepared for a fast-paced environment with limited resources. On the other hand, large companies offer stability and structured career paths but may involve more specialized roles and slower decision-making processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gain Experience First: &lt;/strong&gt;&lt;br&gt;
Instead of fixating on landing your dream job right away, prioritize gaining practical experience from different organizations. Working in diverse environments will help you better understand your strengths, interests, and career preferences. Treat each role as an opportunity to learn and grow professionally.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pursue Personal Projects:&lt;/strong&gt; &lt;br&gt;
Invest time in developing your own projects outside of coursework. These projects not only showcase your technical skills but also demonstrate your creativity and passion for programming. Exploring different domains and technologies through personal projects can help you discover new interests and refine your career goals.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Embrace Confidence: &lt;/strong&gt;&lt;br&gt;
Approach interviews with self-assurance and belief in your abilities. Remember that while you're eager to secure a job, companies are equally eager to hire skilled candidates. Trust in your preparation and qualifications, and convey your enthusiasm for the role during the interview process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Make a Memorable First Impression: &lt;/strong&gt;&lt;br&gt;
Pay attention to the initial moments of the interview as they set the tone for the rest of the conversation. Research the interviewer beforehand to find common ground or shared interests that you can leverage to establish rapport. Engage in meaningful conversation beyond technical skills to leave a positive and lasting impression.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Trust Your Instincts: &lt;/strong&gt;&lt;br&gt;
If you sense discomfort or disrespect during the interview, don't hesitate to excuse yourself. Remember that you'll be working closely with the interviewer if hired, so it's essential to assess their demeanor and professionalism. Prioritize your well-being and seek opportunities where you feel valued and respected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clarify Details Before Committing: &lt;/strong&gt;&lt;br&gt;
Before scheduling an interview, gather essential information such as the base salary, commute distance, and employment type (contract, full-time). Knowing these details upfront can help you make informed decisions and avoid potential mismatches later on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Research and Prepare Thoroughly: &lt;/strong&gt;&lt;br&gt;
Take the time to research the company's background, products, and industry presence before the interview. Platforms like Glassdoor and Indeed offer valuable insights into company culture, interview processes, and employee experiences. Prepare thoughtful questions to demonstrate your genuine interest and commitment to the role.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build a Strong Portfolio: &lt;/strong&gt;&lt;br&gt;
Showcase your skills and projects through an online portfolio or GitHub repository. Include personal projects, class assignments, or contributions to open-source projects to demonstrate your coding abilities and problem-solving skills.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practice Coding Interviews:&lt;/strong&gt;&lt;br&gt;
Prepare for technical interviews by practicing coding challenges, algorithms, and data structures. Websites like LeetCode, HackerRank, and CodeSignal offer a variety of practice problems and mock interviews to help you sharpen your coding skills.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Seek Mentorship: &lt;/strong&gt;&lt;br&gt;
Don't hesitate to reach out to experienced developers or industry professionals for mentorship opportunities. Mentors can provide invaluable advice, guidance, and support as you navigate your career path. Be genuine in your approach, express your eagerness to learn, and be open to feedback and insights from your mentor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stay Persistent and Positive: &lt;/strong&gt;&lt;br&gt;
Landing your first job may take time and perseverance. Stay motivated, continue building your skills, and don't get discouraged by rejection. Every interview and application is an opportunity to learn and grow as a developer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;LinkedIn Strategy - Engaging with HR Managers:&lt;/strong&gt;&lt;br&gt;
Connecting with HR managers on LinkedIn offers a multitude of benefits for job seekers. Firstly, it presents a networking opportunity, allowing individuals to broaden their professional connections within the industry, gaining insights into job openings, organizational culture, and recruitment procedures. Additionally, such connections enhance visibility, potentially prompting companies of interest to take notice and initiate direct contact regarding employment prospects or networking engagements. Moreover, fostering relationships with HR professionals can lead to informational interviews, facilitating a deeper understanding of company dynamics and recruitment protocols, thereby aiding candidates in making informed decisions about potential career paths.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;br&gt;
As you embark on your journey as a junior developer, remember that the path to success is not always linear. It's okay to face challenges and setbacks along the way. What truly matters is your determination, resilience, and passion for software development.&lt;/p&gt;

&lt;p&gt;By following the advice outlined in this article, you're taking proactive steps to set yourself up for success in your career. Whether you're interviewing the interviewer, building your portfolio, or networking with professionals, each action you take brings you closer to achieving your goals.&lt;br&gt;
As you navigate the exciting and ever-evolving world of technology, embrace every opportunity to learn, grow, and adapt. Stay curious, stay humble, and never underestimate the power of perseverance.&lt;/p&gt;

&lt;p&gt;Remember, your journey as a developer is just beginning. Keep coding, keep learning, and keep striving for excellence. Your future in the Tech Industry is bright, and the possibilities are endless.&lt;/p&gt;

&lt;p&gt;Therefore, proceed with assurance, junior developers, and set out on your journey with unwavering determination and fervor. The vast expanse of the tech industry beckons, and through unwavering dedication and diligent effort, you will undoubtedly leave a lasting impression.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best of luck on your journey, and may your passion for technology and innovation continue to fuel your success :-)&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>linkedin</category>
      <category>career</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Selenium Events Listener -WebDriverListener</title>
      <dc:creator>Nael Marwan</dc:creator>
      <pubDate>Fri, 01 Mar 2024 14:15:41 +0000</pubDate>
      <link>https://forem.com/naelabdeljawad/selenium-events-listener-webdriverlistener-3f86</link>
      <guid>https://forem.com/naelabdeljawad/selenium-events-listener-webdriverlistener-3f86</guid>
      <description>&lt;p&gt;The WebDriverEventListenerhas been deprecated, and in response to this change, a new listener called WebDriverListener has been introduced, although it is currently in beta testing. In light of these developments, I have created the WebDriverEventListener, which implements the WebDriverListener interface.&lt;br&gt;
WebDriverEventListener acts as a comprehensive event listener for Selenium WebDriver, allowing us to log events, actions, and errors for each WebDriver interaction and element interaction in your automated tests. It can be a useful debugging and auditing tool to monitor and understand what's happening during test execution.&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.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Sequence;
import org.openqa.selenium.support.events.WebDriverListener;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Set;

public class WebdriverEventListener implements WebDriverListener {

    public void beforeAnyCall(Object target, Method method, Object[] args) {
        Log.info("Before calling method: " + method.getName());
    }

    public void afterAnyCall(Object target, Method method, Object[] args, Object result) {
        Log.info("After calling method: " + method.getName());
    }

    public void onError(Object target, Method method, Object[] args, InvocationTargetException e) {
        Log.error("Error while calling method: " + method.getName() + " - " + e.getMessage());
    }

    public void beforeAnyWebDriverCall(WebDriver driver, Method method, Object[] args) {
        Log.info("Before calling WebDriver method: " + method.getName());
    }

    public void afterAnyWebDriverCall(WebDriver driver, Method method, Object[] args, Object result) {
        Log.info("After calling WebDriver method: " + method.getName());
    }

    public void beforeGet(WebDriver driver, String url) {
        Log.info("Before navigating to URL: " + url);
    }

    public void afterGet(WebDriver driver, String url) {
        Log.info("After navigating to URL: " + url);
    }

    public void beforeGetCurrentUrl(WebDriver driver) {
        Log.info("Before getting current URL.");
    }

    public void afterGetCurrentUrl(String result, WebDriver driver) {
        Log.info("After getting current URL: " + result);
    }

    public void beforeGetTitle(WebDriver driver) {
        Log.info("Before getting page title.");
    }

    public void afterGetTitle(WebDriver driver, String result) {
        Log.info("After getting page title: " + result);
    }

    public void beforeFindElement(WebDriver driver, By locator) {
        Log.info("Before finding element by: " + locator);
    }

    public void afterFindElement(WebDriver driver, By locator, WebElement result) {
        Log.info("After finding element by: " + locator);
    }

    public void beforeFindElements(WebDriver driver, By locator) {
        Log.info("Before finding elements by: " + locator);
    }

    public void afterFindElements(WebDriver driver, By locator, List&amp;lt;WebElement&amp;gt; result) {
        Log.info("After finding elements by: " + locator);
    }

    public void beforeGetPageSource(WebDriver driver) {
        Log.info("Before getting page source.");
    }

    public void afterGetPageSource(WebDriver driver, String result) {
        Log.info("After getting page source.");
    }

    public void beforeClose(WebDriver driver) {
        Log.info("Before closing the WebDriver.");
    }

    public void afterClose(WebDriver driver) {
        Log.info("After closing the WebDriver.");
    }

    public void beforeQuit(WebDriver driver) {
        Log.info("Before quitting the WebDriver.");
    }

    public void afterQuit(WebDriver driver) {
        Log.info("After quitting the WebDriver.");
    }

    public void beforeGetWindowHandles(WebDriver driver) {
        Log.info("Before getting window handles.");
    }

    public void afterGetWindowHandles(WebDriver driver, Set&amp;lt;String&amp;gt; result) {
        Log.info("After getting window handles.");
    }

    public void beforeGetWindowHandle(WebDriver driver) {
        Log.info("Before getting window handle.");
    }

    public void afterGetWindowHandle(WebDriver driver, String result) {
        Log.info("After getting window handle.");
    }

    public void beforeExecuteScript(WebDriver driver, String script, Object[] args) {
        Log.info("Before executing script: " + script);
    }

    public void afterExecuteScript(WebDriver driver, String script, Object[] args, Object result) {
        Log.info("After executing script: " + script);
    }

    public void beforeExecuteAsyncScript(WebDriver driver, String script, Object[] args) {
        Log.info("Before executing async script: " + script);
    }

    public void afterExecuteAsyncScript(WebDriver driver, String script, Object[] args, Object result) {
        Log.info("After executing async script: " + script);
    }

    public void beforePerform(WebDriver driver, Collection&amp;lt;Sequence&amp;gt; actions) {
        Log.info("Before performing actions.");
    }

    public void afterPerform(WebDriver driver, Collection&amp;lt;Sequence&amp;gt; actions) {
        Log.info("After performing actions.");
    }

    public void beforeResetInputState(WebDriver driver) {
        Log.info("Before resetting input state.");
    }

    public void afterResetInputState(WebDriver driver) {
        Log.info("After resetting input state.");
    }

    public void beforeAnyWebElementCall(WebElement element, Method method, Object[] args) {
        Log.info("Before calling WebElement method: " + method.getName());
    }

    public void afterAnyWebElementCall(WebElement element, Method method, Object[] args, Object result) {
        Log.info("After calling WebElement method: " + method.getName());
    }

    public void beforeClick(WebElement element) {
        Log.info("Before clicking on element.");
    }

    public void afterClick(WebElement element) {
        Log.info("After clicking on element.");
    }

    public void beforeSubmit(WebElement element) {
        Log.info("Before submitting a form element.");
    }

    public void afterSubmit(WebElement element) {
        Log.info("After submitting a form element.");
    }

    public void beforeSendKeys(WebElement element, CharSequence... keysToSend) {
        Log.info("Before sending keys to element.");
    }

    public void afterSendKeys(WebElement element, CharSequence... keysToSend) {
        Log.info("After sending keys to element.");
    }

    public void beforeClear(WebElement element) {
        Log.info("Before clearing the text of an element.");
    }

    public void afterClear(WebElement element) {
        Log.info("After clearing the text of an element.");
    }

    public void beforeGetTagName(WebElement element) {
        Log.info("Before getting the tag name of an element.");
    }

    public void afterGetTagName(WebElement element, String result) {
        Log.info("After getting the tag name of an element: " + result);
    }

    public void beforeGetAttribute(WebElement element, String name) {
        Log.info("Before getting an attribute of an element: " + name);
    }

    public void afterGetAttribute(WebElement element, String name, String result) {
        Log.info("After getting an attribute of an element: " + name);
    }

    public void beforeIsSelected(WebElement element) {
        Log.info("Before checking if element is selected.");
    }

    public void afterIsSelected(WebElement element, boolean result) {
        Log.info("After checking if element is selected: " + result);
    }

    public void beforeIsEnabled(WebElement element) {
        Log.info("Before checking if element is enabled.");
    }

    public void afterIsEnabled(WebElement element, boolean result) {
        Log.info("After checking if element is enabled: " + result);
    }

    public void beforeGetText(WebElement element) {
        Log.info("Before getting text from element.");
    }

    public void afterGetText(WebElement element, String result) {
        Log.info("After getting text from element: " + result);
    }

    public void beforeFindElement(WebElement element, By locator) {
        Log.info("Before finding element within element: " + locator);
    }

    public void afterFindElement(WebElement element, By locator, WebElement result) {
        Log.info("After finding element within element: " + locator);
    }

    public void beforeFindElements(WebElement element, By locator) {
        Log.info("Before finding elements within element: " + locator);
    }

    public void afterFindElements(WebElement element, By locator, List&amp;lt;WebElement&amp;gt; result) {
        Log.info("After finding elements within element: " + locator);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How to use the WebdriverEventListener?&lt;br&gt;
This method sets up a ChromeDriver with the ability to log WebDriver events using an event listener. It's a common practice in automated testing to use event listeners to track and log the actions and events that occur during test execution, which can be helpful for debugging and auditing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public WebDriver createWebDriver() {
    ChromeDriverService service = new ChromeDriverService.Builder().usingAnyFreePort().build();
    WebDriver webDriver = new ChromeDriver(service, getCapabilities());
    WebdriverEventListener eventListener = new WebdriverEventListener();
    EventFiringDecorator&amp;lt;WebDriver&amp;gt; decorator = new EventFiringDecorator&amp;lt;&amp;gt;(eventListener);
    return decorator.decorate(webDriver);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;ChromeDriverService Configuration:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This part creates a ChromeDriverService object. A ChromeDriverService is used to configure and manage the ChromeDriver server. Here, it's configured to use any available free port. This means that it will automatically select an available port for the ChromeDriver server to run on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ChromeDriverService service = new ChromeDriverService.Builder().usingAnyFreePort().build();ChromeDriverService Configuration:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;WebDriver Configuration:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WebDriver webDriver = new ChromeDriver(service, getCapabilities());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line creates an instance of the ChromeDriver class, which is a part of Selenium WebDriver for automating Google Chrome browser. It takes two parameters:&lt;br&gt;
service: This is the previously created ChromeDriverService that specifies how the ChromeDriver server should be configured.&lt;br&gt;
getCapabilities(): This likely refers to a method that provides a set of desired capabilities for the ChromeDriver. Desired capabilities are used to configure the browser's behavior during testing, such as the browser version, platform, and more.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Event Listener Setup:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WebdriverEventListener eventListener = new WebdriverEventListener();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A new instance of the WebdriverEventListener class (which you previously provided) is created. This class is an event listener designed to log events and actions related to WebDriver interactions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EventFiringDecorator Configuration:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EventFiringDecorator&amp;lt;WebDriver&amp;gt; decorator = new EventFiringDecorator&amp;lt;&amp;gt;(eventListener);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An EventFiringDecorator is used to wrap the original WebDriver with an event listener. This decorator is a part of Selenium's event-handling mechanism and is used to intercept WebDriver events and delegate them to the specified event listener. In this case, it's configured to use the WebdriverEventListener to log WebDriver events.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Return the Decorated WebDriver:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return decorator.decorate(webDriver);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, the decorated WebDriver, which has the event listener attached, is returned. This WebDriver can be used for test automation, and any interactions with it will be logged by the WebdriverEventListener.&lt;/p&gt;

&lt;p&gt;I trust that this will prove beneficial! 😊&lt;/p&gt;

</description>
      <category>selenium</category>
      <category>webdriver</category>
      <category>testing</category>
      <category>automation</category>
    </item>
    <item>
      <title>Generic Capabilities JSON Loader</title>
      <dc:creator>Nael Marwan</dc:creator>
      <pubDate>Fri, 01 Mar 2024 14:07:59 +0000</pubDate>
      <link>https://forem.com/naelabdeljawad/generic-capabilities-json-loader-165b</link>
      <guid>https://forem.com/naelabdeljawad/generic-capabilities-json-loader-165b</guid>
      <description>&lt;p&gt;Using a generic type for handling capabilities can be a valid approach, especially when we want to create a flexible and fluent API for configuring different types of capabilities (String, int, boolean…).&lt;br&gt;
Let's map together the following Chrome capabilities of our JSON file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "excludeSwitches": "enable-automation",
  "download.prompt_for_download": false,
  "binary": "/usr/bin/google-chrome",
  "chrome.driver.path": "/root/.cache/selenium/chromedriver/linux64/",
  "args": [
    "--start-maximized",
    "--no-sandbox",
    "--disable-dev-shm-usage",
    "--headless"
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: these capabilities are String and boolean types, so the generic implementation makes it type safety.&lt;br&gt;
Generic Capabilities Configuration Loader implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CapabilitiesConfiguration&amp;lt;T extends CapabilitiesConfiguration&amp;lt;T&amp;gt;&amp;gt; {

    public static CapabilitiesConfiguration instance;
    private static final Object lock = new Object();

    public static CapabilitiesConfiguration getInstance() {
        if (instance == null) {
            synchronized (lock) {
                if (instance == null) {
                    instance = new CapabilitiesConfiguration();
                }
            }
        }
        return instance;
    }

    public synchronized CapabilitiesConfiguration&amp;lt;T&amp;gt; getConfigurationFromJSON(String JSONPath, Class&amp;lt;T&amp;gt; configurationClass) {
        CapabilitiesConfiguration&amp;lt;T&amp;gt; configuration = null;
        try {
            File file = new File(JSONPath);
            FileReader fileReader = new FileReader(file);
            BufferedReader bufferedReader = new BufferedReader(fileReader);
            ObjectMapper objectMapper = new ObjectMapper();
            configuration = objectMapper.readValue(bufferedReader, configurationClass);
            bufferedReader.close();
        } catch (Exception e) {
            Log.error(e.getMessage());
        }
        return configuration;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The type of generic we are referring to in CapabilitiesConfiguration&amp;gt; is often known as a recursive bounded type parameter or curiously recurring generic pattern.&lt;br&gt;
Let's break down the components:&lt;br&gt;
T: This is a type parameter that represents a type that extends or is equal to something.&lt;br&gt;
extends CapabilitiesConfiguration: This is a bounded type parameter. It specifies that T there must be a subtype of CapabilitiesConfiguration.&lt;/p&gt;

&lt;p&gt;Putting it together:&lt;br&gt;
T extends CapabilitiesConfiguration: This means that T is a type parameter that must be a subtype of CapabilitiesConfiguration. In other words, any class that extends CapabilitiesConfiguration must use itself (or a subclass of itself) as the type parameter.&lt;/p&gt;

&lt;p&gt;Now let's implement our sub-class of the generic CapabilitiesConfiguration class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Getter
@Setter
public class ChromeConfiguration extends CapabilitiesConfiguration&amp;lt;ChromeConfiguration&amp;gt; {
    @JsonProperty("excludeSwitches")
    private String excludeSwitches;

    @JsonProperty("download.prompt_for_download")
    private boolean downloadPromptForDownload;

    @JsonProperty("binary")
    private String binaryPath;

    @JsonProperty("chrome.driver.path")
    private String driverPath;

    @JsonProperty("args")
    private List&amp;lt;String&amp;gt; args;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;@Getter and &lt;a class="mentioned-user" href="https://dev.to/setter"&gt;@setter&lt;/a&gt;: These Lombok annotations generate getter and setter methods for the class fields. So, we don't need to write them explicitly; Lombok takes care of that during compilation.&lt;br&gt;
ChromeConfiguration extends CapabilitiesConfiguration: It means that ChromeConfiguration is a subtype of CapabilitiesConfiguration with itself as the type parameter. This enforces that any subclass must use itself as the type parameter when extending CapabilitiesConfiguration, as specified by the generic class.&lt;br&gt;
@JsonProperty("property_name"): These annotations are from Jackson library and are used to map the Java class fields to corresponding property names in JSON during serialization and deserialization.&lt;/p&gt;

&lt;p&gt;How to load and use the capabilities?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ChromeConfiguration chromeConfiguration = capsLoader.getConfigurationFromJSON(CHROME_CONFIG_FILE_PATH, ChromeConfiguration.class);
ChromeOptions chromeOptions = new ChromeOptions();
HashMap&amp;lt;String, Object&amp;gt; chromePrefs = new HashMap&amp;lt;&amp;gt;();
chromePrefs.put("download.prompt_for_download", chromeConfiguration.isDownloadPromptForDownload());
chromeOptions.setExperimentalOption("excludeSwitches", new String[]{chromeConfiguration.getExcludeSwitches()});
chromeOptions.setExperimentalOption("prefs", chromePrefs);
chromeOptions.setBinary(chromeConfiguration.getBinaryPath());
chromeConfiguration.getArgs().forEach(chromeOptions::addArguments);
System.setProperty("webdriver.chrome.driver", Objects.requireNonNull(Utils.findAndGetFileName(chromeConfiguration.getDriverPath(), "chromedriver")));
return chromeOptions;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When dealing with a configuration framework that needs to handle a variety of capabilities, using generics in loading capabilities can provide various benefits. Here are some benefits:&lt;br&gt;
Type Safety:&lt;/p&gt;

&lt;p&gt;Generics provide compile-time type checking, ensuring that the correct types are used during the loading process. This helps catch type-related errors early in the development process.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Flexibility:&lt;br&gt;
Generics allow us to create a loading mechanism that can handle different types of capabilities without knowing the specific types at compile time. This flexibility is beneficial when dealing with a diverse set of capabilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reusability:&lt;br&gt;
A generic loading mechanism can be reused for various types of capabilities. The same loading logic can be applied to different configurations, reducing code duplication and promoting a more maintainable codebase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consistency:&lt;br&gt;
Using generics ensures a consistent approach to loading capabilities across different types. This consistency can make the codebase more understandable and easier to maintain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adaptability to Future Changes:&lt;br&gt;
When new types of capabilities are introduced, the generic loading mechanism can often adapt without significant modifications. This adaptability is valuable in scenarios where the set of capabilities may evolve.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easier Maintenance:&lt;br&gt;
With a generic approach, maintaining the loading mechanism becomes more straightforward. Changes and improvements to the loading logic can be applied uniformly across different types of capabilities.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thanks :)&lt;/p&gt;

</description>
      <category>selenium</category>
      <category>webdriver</category>
      <category>java</category>
      <category>generics</category>
    </item>
    <item>
      <title>Automation Common Utilities</title>
      <dc:creator>Nael Marwan</dc:creator>
      <pubDate>Fri, 29 Jan 2021 22:46:11 +0000</pubDate>
      <link>https://forem.com/naelabdeljawad/automation-common-utilities-24p5</link>
      <guid>https://forem.com/naelabdeljawad/automation-common-utilities-24p5</guid>
      <description>&lt;p&gt;Utility classes are an efficient way of allowing you to create methods that you often re-use in your code.&lt;/p&gt;

&lt;p&gt;Adding utilities to your automation infrastructure based on Appium/Selenium is tough and takes a long time to implement so that I’m sharing some common utility classes in Java.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Utility classes criteria:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Utility class should be final.&lt;/li&gt;
&lt;li&gt;A Utility class should contain a private constructor.&lt;/li&gt;
&lt;li&gt;A Utility class should only contain final static fields.&lt;/li&gt;
&lt;li&gt;A Utility class should only contain static methods.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notes: &lt;br&gt;
Used open-source libs only.&lt;br&gt;
Please follow the above criteria in creating your customized utility class.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/naelabdeljawad/f47f125870e13c9472253b84e389adad"&gt;TestNG Retry Listener&lt;/a&gt;&lt;br&gt;
&lt;a href="https://gist.github.com/naelabdeljawad/5e1af8fd7f4c783c8e460182daf8871f"&gt;Appium Utilities&lt;/a&gt;&lt;br&gt;
&lt;a href="https://gist.github.com/naelabdeljawad/95fb86354316e04bc1daabb43006e1ed"&gt;Appium Capabilities CSV Manager&lt;/a&gt;&lt;br&gt;
&lt;a href="https://gist.github.com/naelabdeljawad/896cb822ff65ee071e41d6d8eafe3167"&gt;Selenium Utilities&lt;/a&gt;&lt;br&gt;
&lt;a href="https://gist.github.com/naelabdeljawad/ae402d94b3b5be571bdb99a1790f6358"&gt;PDF Utilities&lt;/a&gt;&lt;br&gt;
&lt;a href="https://gist.github.com/naelabdeljawad/d1075e2e54a640f560d2c428a7485fde"&gt;File Reader Utilities&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy Testing 😊&lt;/p&gt;

</description>
      <category>java</category>
      <category>selenium</category>
      <category>appium</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
