<?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: Elias Nogueira </title>
    <description>The latest articles on DEV Community by Elias Nogueira  (@eliasnogueira).</description>
    <link>https://dev.to/eliasnogueira</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%2F425589%2F74ba0aa9-5ed5-4418-befe-d32b42ae784f.jpg</url>
      <title>DEV Community: Elias Nogueira </title>
      <link>https://dev.to/eliasnogueira</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eliasnogueira"/>
    <language>en</language>
    <item>
      <title>Custom JUnit 5 Extensions for Testing</title>
      <dc:creator>Elias Nogueira </dc:creator>
      <pubDate>Mon, 02 Feb 2026 21:05:49 +0000</pubDate>
      <link>https://dev.to/eliasnogueira/custom-junit-5-extensions-for-testing-hnh</link>
      <guid>https://dev.to/eliasnogueira/custom-junit-5-extensions-for-testing-hnh</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;JUnit 5 extensions are one of those features many teams rely on every day without ever thinking about them. If you use Mockito, Spring Boot tests, or Testcontainers, extensions are already doing a lot of work behind the scenes for you.&lt;/p&gt;

&lt;p&gt;What is far less common is to use the same mechanism deliberately to solve problems in your own test suite. Especially in integration tests, extensions can simplify code, remove repetition, and make tests easier to reason about.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a JUnit 5 extension really is
&lt;/h2&gt;

&lt;p&gt;A JUnit 5 extension is not just a helper class or a utility method. It is a way to hook into the test execution lifecycle.&lt;/p&gt;

&lt;p&gt;When JUnit runs a test, it goes through a well-defined lifecycle. Test classes are discovered, instances are created, methods are executed, and results are collected. At each of these steps, JUnit checks whether there are extensions registered for that test and gives them a chance to participate in the process.&lt;/p&gt;

&lt;p&gt;From a technical point of view, an extension is a plain Java class that implements one or more interfaces from the &lt;code&gt;org.junit.jupiter.api.extension package&lt;/code&gt;. Each interface represents a specific moment in the test lifecycle. Some extensions run before a test class is instantiated, others after each test method, and others only when an exception is thrown.&lt;/p&gt;

&lt;p&gt;Once registered using the &lt;code&gt;@ExtendWith&lt;/code&gt; annotation, the extension becomes part of the execution flow. It reacts to events triggered by the engine instead of being explicitly invoked by the test code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does this matter for any type of tests?
&lt;/h2&gt;

&lt;p&gt;Sometimes, tests often fail for reasons that have nothing to do with business logic. Timing issues, asynchronous processing, external services, and unstable environments are common sources of problems.&lt;/p&gt;

&lt;p&gt;If this kind of logic is handled directly inside test methods, like the common approach of creating helper classes, tests quickly become noisy and hard to maintain. Extensions allow these concerns to live in one place, outside the test logic, while still being applied consistently across the entire test suite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Environment availability check
&lt;/h2&gt;

&lt;p&gt;This example is more of a feature of the testing framework than many tools you already use, such as Testcontainers, Mockito, and others, that provide their own JUnit extension.&lt;/p&gt;

&lt;h3&gt;
  
  
  The problem with environment failures
&lt;/h3&gt;

&lt;p&gt;Let’s think that you have a project that also runs system or end-to-end tests in different environments, like a staging, QA, pre-pro, ephemeral, or whatever environment you have to test. We have all been facing this problem: the environment unavailability.&lt;/p&gt;

&lt;p&gt;We run the test, everything fails, the error message is noisy and misleading, and, only after a few seconds or minutes, we realize that the target system is not running. This is not a test failure; this is an infrastructure failure. This failure can be anything: a backend service, a database, or the message broker, and any other thing in the architecture that can prevent the system, or part of it, from being available.&lt;/p&gt;

&lt;p&gt;There are some symptoms, like connection refused errors, timeouts, stack traces unrelated to the test intent, and dozens of failed tests hiding a single root cause. The approach we will take in the example is: if the environment is not ready, do not run any test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does this not belong in the test code?
&lt;/h3&gt;

&lt;p&gt;The availability of a backend is not part of the test logic, as tests should describe behavior, not infrastructure health checks.&lt;/p&gt;

&lt;p&gt;This makes it a perfect candidate for a JUnit 5 Extension, as it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;runs before tests&lt;/li&gt;
&lt;li&gt;applies consistently&lt;/li&gt;
&lt;li&gt;keeps test code clean&lt;/li&gt;
&lt;li&gt;fails fast with a clear message&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea is to make an environment availability a precondition. As we can influence the test lifecycle in JUnit 5 using a custom extension can do the following if the requirements about the environment availability are not met:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;abort the execution&lt;/li&gt;
&lt;li&gt;or skip the tests with a clear explanation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is exactly what &lt;code&gt;Assumptions.assumeTrue(...)&lt;/code&gt; is designed for.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing the extension
&lt;/h3&gt;

&lt;p&gt;The extension below checks whether a backend health endpoint is reachable before any test runs. If the backend is down, tests are skipped immediately with a clear message.&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;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EnvironmentAvailabilityExtension&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;BeforeAllCallback&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="no"&gt;TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="n"&gt;isEnvironmentReady&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LogManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLogger&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;EnvironmentAvailabilityExtension&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&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;beforeAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ExtensionContext&lt;/span&gt; &lt;span class="n"&gt;context&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;isEnvironmentReady&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="n"&gt;checkEnvironmentHealth&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;Assumptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assumeTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isEnvironmentReady&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"Environment is not available. Start it before running the tests."&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;synchronized&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;checkEnvironmentHealth&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;isEnvironmentReady&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="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="nc"&gt;HttpURLConnection&lt;/span&gt; &lt;span class="n"&gt;connection&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="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="no"&gt;URL&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://my-environment-address/api/health"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toURL&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

            &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpURLConnection&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;openConnection&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setConnectTimeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TIMEOUT&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setReadTimeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TIMEOUT&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setRequestMethod&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;isEnvironmentReady&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getResponseCode&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;HttpURLConnection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HTTP_OK&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;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Environment is not available. Start it before running the tests."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;isEnvironmentReady&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&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;connection&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="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;disconnect&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;p&gt;The method &lt;code&gt;checkEnvironmentHealth()&lt;/code&gt; will check if the health check of the environment is healthy, which means returning an HTTP status of OK (200); then, it will return true or false. This control is done via the BeforeAllCallback interface, where we add the check that the environment is available, validating it via an Assumption action that will make the test not run. As it does not provide any output, we have logged in the catch that the environment is not available, so we can see it in any log.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to use it?
&lt;/h3&gt;

&lt;p&gt;Add the &lt;code&gt;@ExtendWith&lt;/code&gt; on top of the test class within the &lt;code&gt;EnvironmentAvailabilityExtension&lt;/code&gt; class as a parameter.&lt;br&gt;
This will “tell” JUnit to run this extension as part of the test lifecycle, like the &lt;code&gt;@BeforeAll&lt;/code&gt; or &lt;code&gt;@BeforeEach&lt;/code&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="nd"&gt;@ExtendWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;EnvironmentAvailabilityExtension&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldCreateOrder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// test logic&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;
  
  
  Live example
&lt;/h3&gt;

&lt;p&gt;The project &lt;a href="https://github.com/eliasnogueira/restassured-complete-basic-example" rel="noopener noreferrer"&gt;restassured-complete-basic-example&lt;/a&gt; has the example of the environment availability developed as one of the available test strategies: a custom JUnit Extension that won’t run the tests in the case the health check endpoint is not reachable.&lt;/p&gt;

&lt;p&gt;Take a look at the implementation and, maybe, try it out in your local machine: &lt;a href="https://github.com/eliasnogueira/restassured-complete-basic-example/blob/main/src/main/java/com/eliasnogueira/credit/extensions/EnvironmentAvailabilityExtension.java" rel="noopener noreferrer"&gt;https://github.com/eliasnogueira/restassured-complete-basic-example/blob/main/src/main/java/com/eliasnogueira/credit/extensions/EnvironmentAvailabilityExtension.java&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Extensions you are already relying on
&lt;/h2&gt;

&lt;p&gt;Most Java developers already use JUnit 5 extensions, even if they never wrote one themselves.&lt;/p&gt;

&lt;p&gt;Mockito uses an extension to initialize mocks, spies, and argument captors.&lt;br&gt;
Spring relies on an extension to bootstrap the application context and manage dependency injection in tests.&lt;br&gt;
Testcontainers integrates with JUnit to control container startup and shutdown predictably.&lt;/p&gt;

&lt;p&gt;All of these tools hook into the same extension points shown in the examples above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;JUnit 5 extensions are not an advanced feature reserved for framework authors. They are a practical way to keep integration tests focused, readable, and consistent.&lt;/p&gt;

&lt;p&gt;When you see the same setup code, retry logic, or infrastructure concerns appearing across multiple tests, an extension is often the cleanest solution. Once you start using them intentionally, it becomes hard to imagine maintaining a larger integration test suite without them.&lt;/p&gt;

</description>
      <category>unittest</category>
      <category>testing</category>
      <category>junit5</category>
      <category>java</category>
    </item>
    <item>
      <title>Assert with Grace: Custom Soft Assertions using AssertJ for Cleaner Code</title>
      <dc:creator>Elias Nogueira </dc:creator>
      <pubDate>Tue, 19 Nov 2024 20:39:25 +0000</pubDate>
      <link>https://dev.to/eliasnogueira/assert-with-grace-custom-soft-assertions-using-assertj-for-cleaner-code-3nj3</link>
      <guid>https://dev.to/eliasnogueira/assert-with-grace-custom-soft-assertions-using-assertj-for-cleaner-code-3nj3</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;If you don’t know what a soft assertion is, please read &lt;a href="https://eliasnogueira.com/soft-asserts-why-should-you-use-them-for-unit-and-integration-tests/" rel="noopener noreferrer"&gt;Soft Asserts – Why should you use them for Unit and Integration tests&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;This article is a continuation of &lt;a href="https://eliasnogueira.com/assert-with-grace-custom-assertions-for-cleaner-code/" rel="noopener noreferrer"&gt;Assert with Grace: Custom Assertions for Cleaner Code&lt;/a&gt; which shows you how to create custom assertions using AssertJ. Here you will learn how to extend its approach to use the soft assertion approach on top of the custom assertion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Soft Assertions with AssertJ
&lt;/h2&gt;

&lt;p&gt;You can have a hard assertion using the &lt;code&gt;Assertions&lt;/code&gt; class from AssertJ or a custom one. To get all the benefits of the soft assertion we need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;have a custom assertion implemented&lt;/li&gt;
&lt;li&gt;create the custom soft assertion class and extend the &lt;code&gt;AbstractSoftAssertions&lt;/code&gt; from AssertJ&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The custom assertion
&lt;/h3&gt;

&lt;p&gt;You learned how to create a custom assertion in the &lt;a href="https://eliasnogueira.com/assert-with-grace-custom-assertions-for-cleaner-code/" rel="noopener noreferrer"&gt;Assert with Grace: Custom Assertions for Cleaner Code&lt;/a&gt; article. It looks like this:&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;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimulationAssert&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractAssert&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SimulationAssert&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Simulation&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nf"&gt;SimulationAssert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Simulation&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SimulationAssert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&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;static&lt;/span&gt; &lt;span class="nc"&gt;SimulationAssert&lt;/span&gt; &lt;span class="nf"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Simulation&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SimulationAssert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;SimulationAssert&lt;/span&gt; &lt;span class="nf"&gt;hasValidInstallments&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;isNotNull&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;actual&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstallments&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstallments&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;failWithMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Installments must be must be equal or greater than 2 and equal or less than 48"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;SimulationAssert&lt;/span&gt; &lt;span class="nf"&gt;hasValidAmount&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;isNotNull&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;minimum&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;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1.000"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;maximum&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;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"40.000"&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;actual&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAmount&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAmount&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maximum&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;failWithMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Amount must be equal or greater than $ 1.000 or equal or less than than $ 40.000"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&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;p&gt;The usage of the custom assertion shows more legibility in the test as well as sends the responsibility of testing the valid values to it:&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;class&lt;/span&gt; &lt;span class="nc"&gt;SimulationsCustomAssertionTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;simulationErrorAssertion&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;simulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Simulation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;cpf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"9582728395"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"john@gmail.com"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;amount&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;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1.500"&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="na"&gt;installments&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;insurance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;SimulationAssert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;simulation&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;hasValidInstallments&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;SimulationAssert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;simulation&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;hasValidAmount&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;p&gt;With the custom assertion on hand, it’s time to implement the custom soft assertion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the custom soft assertion
&lt;/h3&gt;

&lt;p&gt;There is an easy process to create the custom soft assertion where the precondition is to have a custom assertion implemented. Given the previous article, we have the &lt;code&gt;SimulationAssert&lt;/code&gt; class as the custom assertion and will create the &lt;code&gt;SimulationSoftAssert&lt;/code&gt; as a custom soft assertion. These are the steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extend the &lt;code&gt;AbstractSoftAssertions&lt;/code&gt; class&lt;/li&gt;
&lt;li&gt;Create the &lt;code&gt;assertThat()&lt;/code&gt; method with:

&lt;ul&gt;
&lt;li&gt;the method returns an object as the custom assertion class&lt;/li&gt;
&lt;li&gt;a parameter to the subject of the assertion&lt;/li&gt;
&lt;li&gt;the method returns the method proxy where the parameters are the custom assertion class and the subject of the assertion&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Create the &lt;code&gt;assertSoftly()&lt;/code&gt; method with:

&lt;ul&gt;
&lt;li&gt;a parameter as a Consumer to the custom soft assert class&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;SoftAssertionsProvider.assertSoftly()&lt;/code&gt; method as the parameter is the custom soft assertion class and the method parameter&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The steps look complex, but in practice, you will end up with this:&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;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimulationSoftAssert&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractSoftAssertions&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;SimulationAssert&lt;/span&gt; &lt;span class="nf"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Simulation&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SimulationAssert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Simulation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;);&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;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;assertSoftly&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Consumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SimulationSoftAssert&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;softly&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;SoftAssertionsProvider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertSoftly&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SimulationSoftAssert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;softly&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;h3&gt;
  
  
  Using the Custom Soft Assertion
&lt;/h3&gt;

&lt;p&gt;The AssertJ SoftAssertion class is responsible for the soft assertions. This is the example applicable to the Simulation context:&lt;/p&gt;

&lt;p&gt;The AssertJ &lt;a href="https://assertj.github.io/doc/#assertj-core-soft-assertions" rel="noopener noreferrer"&gt;SoftAssertion&lt;/a&gt; class is responsible for the soft assertions. This is the example applicable to the &lt;code&gt;Simulation&lt;/code&gt; context:&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="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;normalSoftAssertion&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;SoftAssertions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertSoftly&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;softly&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;simulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Simulation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;cpf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"9582728395"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"john@gmail.com"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;amount&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;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"500"&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="na"&gt;installments&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;insurance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;softly&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;simulation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstallments&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;isEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;softly&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;simulation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAmount&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;isEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&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;p&gt;The “problem” using it is that we won’t be able to use the custom assertion we have created. In the example above you can see the assertions in the installments and amount using the &lt;code&gt;isEqualTo()&lt;/code&gt; as the &lt;code&gt;SoftAssertions&lt;/code&gt; class has no access to the custom assertion.&lt;/p&gt;

&lt;p&gt;We have solved this problem by creating the custom soft assertions class. So, instead of using the SoftAssertions class we will use the custom one: &lt;code&gt;SimulationSoftAssert&lt;/code&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="nd"&gt;@Test&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;simulationValidationErrorSoftAssertion&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;simulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Simulation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;cpf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"9582728395"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"john@gmail.com"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;amount&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;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"500"&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="na"&gt;installments&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;insurance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;SimulationSoftAssert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertSoftly&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;softly&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;softly&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;simulation&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;hasValidInstallments&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;softly&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;simulation&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;hasValidAmount&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;p&gt;The &lt;code&gt;SimulationSoftAssert.assertSoftly()&lt;/code&gt; is a provider for the soft assertion that will call all internal methods to be able to manage the errors and other activities during the assertions. The &lt;code&gt;assertThat()&lt;/code&gt; in use, inside the &lt;code&gt;assertSoftly()&lt;/code&gt; will be the custom one which will have access to the custom assertion by the &lt;code&gt;proxy()&lt;/code&gt; between the soft assert and the subject of the assertion.&lt;/p&gt;

&lt;p&gt;Using this approach we have the custom assertions available in the soft assertion by the implementation of a custom one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The end
&lt;/h2&gt;

&lt;p&gt;That’s all folks!&lt;/p&gt;

&lt;p&gt;You can find a fully implemented and working example in the &lt;a href="https://github.com/eliasnogueira/credit-api" rel="noopener noreferrer"&gt;credit-api&lt;/a&gt; project, where you can see the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/eliasnogueira/credit-api/blob/main/src/test/java/com/eliasnogueira/credit/assertion/SimulationSoftAssert.java" rel="noopener noreferrer"&gt;SimulationAssert&lt;/a&gt; class&lt;/li&gt;
&lt;li&gt;Test usage in the &lt;a href="https://github.com/eliasnogueira/credit-api/blob/main/src/test/java/com/eliasnogueira/credit/tests/SimulationsCustomAssertionTest.java" rel="noopener noreferrer"&gt;SimulationsCustomAssertionTest&lt;/a&gt; class&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>testing</category>
      <category>java</category>
      <category>assertj</category>
      <category>unittest</category>
    </item>
    <item>
      <title>How to simulate real BeforeAll and AfterAll in JUnit 5</title>
      <dc:creator>Elias Nogueira </dc:creator>
      <pubDate>Fri, 05 Jul 2024 08:51:00 +0000</pubDate>
      <link>https://dev.to/eliasnogueira/how-to-simulate-real-beforeall-and-afterall-in-junit-5-gd5</link>
      <guid>https://dev.to/eliasnogueira/how-to-simulate-real-beforeall-and-afterall-in-junit-5-gd5</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;JUnit 5 is a well-known Java Testing Framework/Library across developers. It’s the evolution of JUnit 4 and carries with it a lot of awesome features. One of the most important ones is setting pre and post-conditions as knowing by the terms Before (pre-condition) and After (post-condition).&lt;/p&gt;

&lt;p&gt;It has 2 supported ways: Before/After All and Before/After Each.&lt;br&gt;
The “All” part means that a code block can be executed as pre or post-condition before or after it can initialize all tests. The “Each” part means that a code block can be executed as a pre or post-condition before or after each test.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://junit.org/junit5/docs/snapshot/user-guide/#overview" rel="noopener noreferrer"&gt;JUnit 5 official docs&lt;/a&gt; say the following about these strategies, which are annotations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Annotation&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@BeforeEach&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Denotes that the annotated method should be executed &lt;strong&gt;before each&lt;/strong&gt; &lt;code&gt;@Test&lt;/code&gt;, &lt;code&gt;@RepeatedTest&lt;/code&gt;, &lt;code&gt;@ParameterizedTest&lt;/code&gt;, or &lt;code&gt;@TestFactory&lt;/code&gt; method in the current class; analogous to JUnit 4’s &lt;code&gt;@Before&lt;/code&gt;. Such methods are inherited unless they are overridden&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@AfterEach&lt;/td&gt;
&lt;td&gt;Denotes that the annotated method should be executed &lt;strong&gt;after each&lt;/strong&gt; &lt;code&gt;@Test&lt;/code&gt;, &lt;code&gt;@RepeatedTest&lt;/code&gt;, &lt;code&gt;@ParameterizedTest&lt;/code&gt;, or &lt;code&gt;@TestFactory&lt;/code&gt; method in the current class; analogous to JUnit 4’s @After. Such methods are inherited unless they are overridden.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@BeforeAll&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Denotes that the annotated method should be executed &lt;strong&gt;before all&lt;/strong&gt; &lt;code&gt;@Test&lt;/code&gt;, &lt;code&gt;@RepeatedTest&lt;/code&gt;, &lt;code&gt;@ParameterizedTest&lt;/code&gt;, and &lt;code&gt;@TestFactory&lt;/code&gt; methods in the current class; analogous to JUnit 4’s &lt;code&gt;@BeforeClass&lt;/code&gt;. Such methods are inherited unless they are overridden and must be static unless the “per-class” test instance lifecycle is used.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@AfterAll&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Denotes that the annotated method should be executed &lt;strong&gt;after all&lt;/strong&gt; &lt;code&gt;@Test&lt;/code&gt;, &lt;code&gt;@RepeatedTest&lt;/code&gt;, &lt;code&gt;@ParameterizedTest&lt;/code&gt;, and &lt;code&gt;@TestFactory&lt;/code&gt; methods in the current class; analogous to JUnit 4’s &lt;code&gt;@AfterClass&lt;/code&gt;. Such methods are inherited unless they are overridden and must be static unless the “per-class” test instance lifecycle is used.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  What problem we are trying to solve
&lt;/h2&gt;

&lt;p&gt;Only by looking at the annotations, we understand that it covers most of the scenarios we want for our tests.&lt;br&gt;
We have the &lt;code&gt;@BeforeAll&lt;/code&gt; and &lt;code&gt;@AfterAll&lt;/code&gt; annotations as a general pre or post-condition.&lt;/p&gt;

&lt;p&gt;One common testing pattern applied in good testing architectures is the BaseTest class: a place where we can add pre and post-conditions that will shared across different tests by inheritance. Normally, we want to control these conditions in different ways. Developers have different ways to control it through the BaseTest pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;open the browser only once when any test starts to save time&lt;/li&gt;
&lt;li&gt;keep a container (Testcontainer) opened for different test classes&lt;/li&gt;
&lt;li&gt;ingest data before any test is executed and remove it after all are executed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have bad news: JUnit 5 doesn’t have a way to control the three mentioned scenarios as the &lt;code&gt;@BeforeAll&lt;/code&gt; and &lt;code&gt;@AfterAll&lt;/code&gt; are executed per test instance, meaning per test class. Other frameworks like TestNG &lt;a href="https://testng.org/#_annotations" rel="noopener noreferrer"&gt;have this ability&lt;/a&gt; called &lt;code&gt;@BeforeSuite&lt;/code&gt; and &lt;code&gt;@AfterSuite&lt;/code&gt;, and it’s exactly what we want that JUnit 5 does not support.&lt;/p&gt;

&lt;p&gt;Let’s understand how we could use JUnit 5 for this and how to fix this problem.&lt;/p&gt;
&lt;h2&gt;
  
  
  The BeforeAllCallback and AfterAllCallback interfaces
&lt;/h2&gt;

&lt;p&gt;You might do some Google search, like I did infinite times, encountering the &lt;a href="https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/extension/BeforeAllCallback.html" rel="noopener noreferrer"&gt;BeforeAllCallback&lt;/a&gt; and &lt;a href="https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/extension/AfterAllCallback.html" rel="noopener noreferrer"&gt;AfterAllCallback&lt;/a&gt; interfaces which are &lt;a href="https://junit.org/junit5/docs/snapshot/user-guide/#extensions-registration" rel="noopener noreferrer"&gt;Extensions&lt;/a&gt; of &lt;a href="https://junit.org/junit5/docs/snapshot/user-guide/#extensions-lifecycle-callbacks" rel="noopener noreferrer"&gt;Testing Lifecycle Callbacks&lt;/a&gt;. It seems a good solution as these interfaces enable you to run the &lt;code&gt;@BeforeAll&lt;/code&gt; or &lt;code&gt;@AfterAll&lt;/code&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyExtension&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;BeforeAllCallback&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AfterAllCallback&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&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;afterAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ExtensionContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// pre general condition&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&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;beforeAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ExtensionContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// post general conditions&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;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%2Ftv2qmqqvp825z6xlju23.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%2Ftv2qmqqvp825z6xlju23.png" alt="UML diagram showing the current way of using the pre and postcondition annotations" width="631" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The UML diagram shows a BaseTest using a JUnit 5 Extension called &lt;code&gt;MyExtension&lt;/code&gt; that implements the &lt;code&gt;BeforeAllCallback&lt;/code&gt; and &lt;code&gt;AfterAllCallback&lt;/code&gt;. The base test is used in the &lt;code&gt;FeatureTest1&lt;/code&gt; and &lt;code&gt;FeatureTest2&lt;/code&gt;. Note that the &lt;code&gt;MyExtension&lt;/code&gt; has the &lt;code&gt;beforeAll&lt;/code&gt; and &lt;code&gt;afterAllMethods&lt;/code&gt;, as well as the &lt;code&gt;BaseTest&lt;/code&gt; has it.&lt;/p&gt;

&lt;p&gt;It solves the problem as the &lt;code&gt;MyExtension&lt;/code&gt; would serve as the global before and after, as the ones in the &lt;code&gt;BaseTest&lt;/code&gt; would run per test instance, meaning running when &lt;code&gt;Feature1Test&lt;/code&gt; and &lt;code&gt;Feature2Test&lt;/code&gt; run. Unfortunately, it’s not the case. If we would add only a &lt;code&gt;System.out.println()&lt;/code&gt; call in each method, the output would be the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.eliasnogueira.feature1.Feature1Test
MyExtension.beforeAll
BaseTest.beforeAll
Feature1Test.test1
Feature1Test.test2
Feature1Test.test3
BaseTest.afterAll
MyExtension.afterAll
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.018 s -- in com.eliasnogueira.feature1.Feature1Test

[INFO] Running com.eliasnogueira.feature2.Feature2Test
MyExtension.beforeAll
BaseTest.beforeAll
Feature2Test.test1
Feature1Test.test2
BaseTest.afterAll
MyExtension.afterAll
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 s -- in com.eliasnogueira.feature2.Feature2Test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that the methods in the &lt;code&gt;MyExtension&lt;/code&gt; run for every test class, as well as the &lt;code&gt;BaseTest&lt;/code&gt;. This means that JUnit runs it per test instance. Unfortunately, JUnit 5 doesn’t have a solution for a general precondition before or after any test for the whole test execution.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Want to see it in action?&lt;br&gt;
– Clone this repo: git clone &lt;a href="https://github.com/eliasnogueira/junit5-before-after-all" rel="noopener noreferrer"&gt;https://github.com/eliasnogueira/junit5-before-after-all&lt;/a&gt;&lt;br&gt;
– Switch to the no-solution branch&lt;br&gt;
– Run mvn test&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to solve it
&lt;/h2&gt;

&lt;p&gt;There is a light at the end of the tunnel and it’s not difficult. Like everyone, I Google it and found an interesting workaround on this Stackoverflow thread: &lt;a href="https://stackoverflow.com/questions/43282798/in-junit-5-how-to-run-code-before-all-test" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/43282798/in-junit-5-how-to-run-code-before-all-test&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Be aware that this is a workaround and might not work in future JUnit versions.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The solution is based on using the &lt;code&gt;BeforeAllCallback&lt;/code&gt; interface, with a thread lock in case parallel tests run to solve the general precondition and the JUnit storage mechanism to mimic the postcondition using the &lt;a href="https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/extension/ExtensionContext.Store.CloseableResource.html" rel="noopener noreferrer"&gt;ExtensionContext.Store.CloseableResource&lt;/a&gt; interface. Don’t worry, I will break down the implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The example
&lt;/h3&gt;

&lt;p&gt;It is a simple one just to show you that the approach works. The example shows a general BaseTest and a BaseTest per feature, where an extension will be created to give the ability of execution a general pre and postcondition.&lt;/p&gt;

&lt;h3&gt;
  
  
  The extension implementation
&lt;/h3&gt;

&lt;p&gt;The implementation can be done in four steps, and the final solution will look 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%2F2mzuodqfxn5lvc24e3tp.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%2F2mzuodqfxn5lvc24e3tp.png" alt="UML diagram showing the proposal implementation of the before and after to solve the current problem" width="435" height="554"&gt;&lt;/a&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="mi"&gt;1&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;SetupExtension&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;BeforeAllCallback&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Store&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CloseableResource&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt; 
&lt;span class="mi"&gt;3&lt;/span&gt;     &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Lock&lt;/span&gt; &lt;span class="no"&gt;LOCK&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;ReentrantLock&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;     &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;started&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt; 
&lt;span class="mi"&gt;6&lt;/span&gt;     &lt;span class="nd"&gt;@Override&lt;/span&gt;
&lt;span class="mi"&gt;7&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;beforeAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ExtensionContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;         &lt;span class="no"&gt;LOCK&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lock&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt;  
&lt;span class="mi"&gt;10&lt;/span&gt;         &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;11&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;started&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;12&lt;/span&gt;                &lt;span class="n"&gt;started&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;13&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;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[pre-condition] Should run only once"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;14&lt;/span&gt;                &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRoot&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getStore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Namespace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GLOBAL&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Placeholder for post condition"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;15&lt;/span&gt;            &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="mi"&gt;16&lt;/span&gt;        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;17&lt;/span&gt;            &lt;span class="c1"&gt;// free the access&lt;/span&gt;
&lt;span class="mi"&gt;18&lt;/span&gt;            &lt;span class="no"&gt;LOCK&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;unlock&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="mi"&gt;19&lt;/span&gt;        &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="mi"&gt;20&lt;/span&gt;    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="mi"&gt;21&lt;/span&gt; 
&lt;span class="mi"&gt;22&lt;/span&gt; 
&lt;span class="mi"&gt;23&lt;/span&gt;    &lt;span class="nd"&gt;@Override&lt;/span&gt;
&lt;span class="mi"&gt;24&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;close&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;25&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;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[post-condition] Should run only once"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;26&lt;/span&gt;    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Implementation of the necessary interfaces&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Line 1 shows that the two interfaces: &lt;code&gt;BeforeAllCallback&lt;/code&gt; overriding the &lt;code&gt;beforeAll()&lt;/code&gt; method which will control the general precondition and &lt;code&gt;ExtensionContext.Store.CloseableResource&lt;/code&gt; overrides the &lt;code&gt;close()&lt;/code&gt; method which will mimic the general postcondition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Controlling the single execution of the beforeAll&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To guarantee that it will be executed only once one strategy must be applied: control that it has started, so the &lt;code&gt;beforeAll()&lt;/code&gt; won't execute again.&lt;/p&gt;

&lt;p&gt;Line 8 shows that we are locking the thread. This is necessary to ensure that any parallel execution will be possible. Line 11 checks if the code had any previous execution. When it's the first time the &lt;code&gt;boolean started&lt;/code&gt; is set as &lt;code&gt;true&lt;/code&gt; ensure it won't go to the code block in the subsequent runs. The &lt;code&gt;finally&lt;/code&gt; section unlocks the thread.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementing the general precondition&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Any necessary implementation for the general precondition should be placed inside the &lt;code&gt;if&lt;/code&gt; condition, simple like that. We can see this in the line 13.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add a signal (storage) to mimic the general postcondition&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The way to mimic the general postcondition here is through the &lt;a href="https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/extension/ExtensionContext.Store.html" rel="noopener noreferrer"&gt;Store&lt;/a&gt;. In JUnit 5, we can store objects for later retrieval in an extension and it can be done using the &lt;code&gt;getStore(context).put(key, value)&lt;/code&gt; where the &lt;code&gt;context&lt;/code&gt; is the root or current context and the &lt;code&gt;key,value&lt;/code&gt; are the key and value to add to its storage.&lt;/p&gt;

&lt;p&gt;Line 14 creates a dummy store object for later usage in the automatic &lt;code&gt;close()&lt;/code&gt; method invocation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implement the general postcondition&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;close()&lt;/code&gt; method from the &lt;code&gt;ExtensionContext.Store.CloseableResource&lt;/code&gt; interface will be invoked when the extension lifecycle ends [&lt;a href="https://junit.org/junit5/docs/current/user-guide/#extensions-keeping-state" rel="noopener noreferrer"&gt;reference&lt;/a&gt;]. This is the last opportunity to execute any code before the program exits. In this way, we can simulate the general postcondition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code example
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/eliasnogueira/junit5-before-after-all" rel="noopener noreferrer"&gt;https://github.com/eliasnogueira/junit5-before-after-all&lt;/a&gt; project shows the implementation based on this article’s explanation matching the diagram in “The example” section.&lt;/p&gt;

&lt;p&gt;While running the tests you will see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.eliasnogueira.feature1.Feature1Test
[pre-condition] Should run only once
BaseTest.beforeAll
BaseFeature1Test.beforeAll
Feature1Test.test1
Feature1Test.test2
Feature1Test.test3
BaseFeature1Test.afterAll
BaseTest.afterAll
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.019 s -- in com.eliasnogueira.feature1.Feature1Test

[INFO] Running com.eliasnogueira.feature2.Feature2Test
BaseTest.beforeAll
BaseFeature2Test.beforeAll
Feature2Test.test1
Feature1Test.test2
BaseFeature2Test.afterAll
BaseTest.afterAll
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 s -- in com.eliasnogueira.feature2.Feature2Test
[post-condition] Should run only once
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the general precondition is the text output as &lt;code&gt;[pre-condition] Should run only once&lt;/code&gt; and the general postcondition is the output as &lt;code&gt;[post-condition] Should run only once&lt;/code&gt;. You can see them at the beginning and the end of all test executions, respectively.&lt;/p&gt;

&lt;p&gt;Using this simple approach you can have the general pre and postcondition in your code.&lt;br&gt;
Happy tests!&lt;/p&gt;

</description>
      <category>unittest</category>
      <category>junit</category>
      <category>java</category>
      <category>testing</category>
    </item>
    <item>
      <title>JUnit 5 – When to use CSV Providers</title>
      <dc:creator>Elias Nogueira </dc:creator>
      <pubDate>Sun, 10 Mar 2024 21:38:56 +0000</pubDate>
      <link>https://dev.to/eliasnogueira/junit-5-when-to-use-csv-providers-3bo1</link>
      <guid>https://dev.to/eliasnogueira/junit-5-when-to-use-csv-providers-3bo1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This article belongs to the &lt;a href="https://www.eliasnogueira.com/managing-test-data/" rel="noopener noreferrer"&gt;Managing Test Data&lt;/a&gt; series.&lt;br&gt;
I will show you different ways to smartly use testing framework features when the date changes but the test output is the same.&lt;/p&gt;

&lt;p&gt;In this article, you will see one use case for the &lt;code&gt;@CsvSource&lt;/code&gt; and &lt;code&gt;@CsvFileSource&lt;/code&gt; features. These annotations are particularly useful when you want to provide test data in CSV (Comma-Separated Values) format either directly in the source code or from an external file.&lt;/p&gt;
&lt;h2&gt;
  
  
  @CsvSource
&lt;/h2&gt;

&lt;p&gt;This Source of Argument in JUnit 5 allows you to use the data as CSV values to allow you either a fast prototype of a CSV file consumption in a test or by the simple use of it to give you the advantage of readability for small data sets. It has different ways to configure it, but let’s focus first on the basic usage.&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;class&lt;/span&gt; &lt;span class="nc"&gt;CsvSourceTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;MAXIMUM_PRICE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"30.0"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Products should not exceed the maximum price"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@ParameterizedTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"product ''{0}'' of amount ${1} does not exceeds $"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;MAXIMUM_PRICE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@CsvSource&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;
            &lt;span class="s"&gt;"Micro SD Card 16Gb, 6.09"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"JBL GO 2, 22.37"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"iPad Air Case, 14.99"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;

    &lt;span class="o"&gt;})&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;productsLassThan&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;product&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;isNotEmpty&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;isLessThanOrEqualTo&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;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MAXIMUM_PRICE&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;p&gt;Lines 6 to 11 show you the basic usage of the &lt;code&gt;@CsvSource&lt;/code&gt;. Note that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The CSV data is placed between brackets in the annotation&lt;/li&gt;
&lt;li&gt;Each CSV line has double quotes at the beginning and end of it&lt;/li&gt;
&lt;li&gt;All the values are separated by a comma, after the end of the double quotes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The test output will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CsvSourceTest
└─ Products should not exceed the maximum price
  ├─ [1] product 'Micro SD Card 16Gb' of amount $6.09 does not exceeds $30.0 ✔
  ├─ [2] product 'JBL GO 2' of amount $22.37 does not exceeds $30.0 ✔
  └─ [3] product 'iPad Air Case' of amount $14.99 does not exceeds $30.0 ✔
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Annotation configurations
&lt;/h3&gt;

&lt;p&gt;There are different ways to change the @CsvSource behavior:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Annotation configuration&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;This is the default.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;delimiter&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Set the delimiter as a char. The default value is a comma (&lt;code&gt;,&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;delimiterString&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Set the delimiter as a String. The default is a comma (&lt;code&gt;,&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;emptyValue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Set what will be added as an empty value. The default is an empty value set as a double quote (&lt;code&gt;""&lt;/code&gt;) The empty value should be added as a single quote on the line value.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ignoreLeadingAndTrailingWhitespace&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The leading and trailing whitespace is automatic tribber by default. Set it to &lt;code&gt;true&lt;/code&gt; to ignore it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maxCharsPerColum&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sets the max chars in the column. The default is &lt;code&gt;4096&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nullValues&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Add the ability to set a specific value to the CSv to &lt;code&gt;null&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;quoteChar&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Determine which character will be used to quote the value. You quote the value when you need to add either a space or any char that might fail the process of reading the line. The default is single quotes (&lt;code&gt;''&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;textBlock&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allows you to use the Text Blocks feature of Java &amp;gt;= 15. It also gives the ability to add comments in the data source which must begin with &lt;code&gt;#&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useHeadersInDisplayName&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Set to true when you want to use a header in the first line. This option is set by default as &lt;code&gt;false&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When you use a configuration the &lt;code&gt;value&lt;/code&gt; attribute must be explicitly declared. You see the example in the below extra explanation.&lt;/p&gt;

&lt;h4&gt;
  
  
  nullValues
&lt;/h4&gt;

&lt;p&gt;Use it when you want to make a specific value to null.&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="nd"&gt;@CsvSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nullValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"6.09"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"Micro SD Card 16Gb, 6.09"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"JBL GO 2, 22.37"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"iPad Air Case, 14.99"&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;p&gt;In the code snippet above you can see that the &lt;code&gt;nullValues&lt;/code&gt; is using &lt;code&gt;"6.09"&lt;/code&gt;. The first value the &lt;code&gt;@CsvSource&lt;/code&gt; contains this value, so it will be replaced by a null value instead of using the original one.&lt;/p&gt;

&lt;h4&gt;
  
  
  textBlock
&lt;/h4&gt;

&lt;p&gt;It allows you to use the Text Blocks feature from Java &amp;gt;= 15, so you don’t need to wrap up the value in the curly brackets. Instead, use the """ as you can see in the example below.&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="nd"&gt;@CsvSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;textBlock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""
        "Micro SD Card 16Gb, 6.09",
        "JBL GO 2, 22.37",
        "iPad Air Case, 14.99"
        """&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why using @CsvSource?
&lt;/h3&gt;

&lt;p&gt;Inline CSV data will make the test method more readable and concise, especially when you are dealing with a small number of test cases, so you get the benefit of readability and conciseness.&lt;/p&gt;

&lt;p&gt;All test data is directly visible within the test method, making it easy for developers to understand the different scenarios being tested without having to navigate to external files adding immediate visilibity, also reducing external dependencies since the test data is embedded within the source code, you don’t need external CSV files, which can simplify the project structure and reduce dependencies on external resources.&lt;/p&gt;

&lt;p&gt;It’s easy to maintain for a small set of test data, helping you to prototype possible scenarios using a CSV file without adding all the dependencies, external files, and complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  @CsvFileSource
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;@CsvFileSource&lt;/code&gt; allows you to provide test data from an external CSV file. This is especially useful when you have a larger set of test data that you want to manage separately from your test code.&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;class&lt;/span&gt; &lt;span class="nc"&gt;CsvFileSourceTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;MAXIMUM_PRICE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"30.0"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Products should not exceed the maximum price"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@ParameterizedTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"product ''{0}'' of amount ${1} does not exceeds $"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;MAXIMUM_PRICE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@CsvFileSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/products.csv"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;productsLassThan&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;product&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;isNotEmpty&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;isLessThanOrEqualTo&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;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MAXIMUM_PRICE&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;p&gt;Line 6 shows the usage of the &lt;code&gt;@CsvFileSource&lt;/code&gt;. Not that is using the attribute &lt;code&gt;resources&lt;/code&gt;, which will look at the file provided in the resource folders. The default behavior is also to expect the CSV file without a header. You can see a possible file for this 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;Micro SD Card 16Gb,6.09
JBL GO 2,22.37
iPad Air Case, 14.99
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The particularities
&lt;/h3&gt;

&lt;p&gt;These are the following particularities compared to the &lt;code&gt;@CsvSource&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Same configuration as the @CsvSource
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;@CsvFileSource&lt;/code&gt; has the same annotation configuration as the &lt;code&gt;@CsvSource&lt;/code&gt;, except for the change in the expected quoteChar as it expects double quotes (&lt;code&gt;""&lt;/code&gt;) instead of single ones.&lt;/p&gt;

&lt;h4&gt;
  
  
  Extra configurations
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Annotation configuration&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;files&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read the external file as a file, so it requires a full path based on the project classpath.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;numLinesToSkip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Skip N lines as N is the number of lines to skip. This is useful when you have a header in the file, where you can set it as &lt;code&gt;1&lt;/code&gt;. The default value is &lt;code&gt;0&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;encoding&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Changes the file encoding. The default value is &lt;code&gt;UTF-8&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h5&gt;
  
  
  resources and files
&lt;/h5&gt;

&lt;p&gt;I believe you noticed that both are in the plural. This means that you can set multiple files. Only single quotes are necessary when you add only one file, as you can see in the previous example.&lt;/p&gt;

&lt;p&gt;In case, you want to merge multiple files, simply add the files separated by commas wrapped up in curly brackets.&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="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Products should not exceed the maximum price"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@ParameterizedTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"product ''{0}'' of amount ${1} does not exceeds $"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;MAXIMUM_PRICE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@CsvFileSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"/products.csv"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/products-no.csv"&lt;/span&gt;&lt;span class="o"&gt;},&lt;/span&gt; &lt;span class="n"&gt;numLinesToSkip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;productsLassThan&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;product&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;isNotEmpty&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;isLessThanOrEqualTo&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;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MAXIMUM_PRICE&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;p&gt;Line 3 shows the usage of two files: &lt;code&gt;products.csv&lt;/code&gt; and &lt;code&gt;products-no.csv&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;They must share the same columns you are using in your parameter conversion, the ones you add in your test like &lt;code&gt;String product&lt;/code&gt; and &lt;code&gt;BigDecimal amount&lt;/code&gt; in this example.&lt;/p&gt;

&lt;p&gt;If you use a column and parameter that is present in one file, but not in the other, a &lt;code&gt;ParameterResolutionException&lt;/code&gt; will be thrown.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use these annotations?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;@CsvFileSource&lt;/code&gt; is straightforward: use it when you need to use an external CSV file in your tests.&lt;/p&gt;

&lt;p&gt;The author recommends you use the &lt;code&gt;@CsvSource&lt;/code&gt; while protecting your data-driven tests using only primitive values or object-related ones like String, Integer, and so on. Otherwise, use any other &lt;a href="https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests-sources" rel="noopener noreferrer"&gt;Source of Arguments&lt;/a&gt; provided by JUnit 5.&lt;/p&gt;

</description>
      <category>java</category>
      <category>junit</category>
      <category>testing</category>
    </item>
    <item>
      <title>One of the most underrated Maven configurations: maven.config</title>
      <dc:creator>Elias Nogueira </dc:creator>
      <pubDate>Tue, 27 Feb 2024 16:06:52 +0000</pubDate>
      <link>https://dev.to/eliasnogueira/one-of-the-most-underrated-maven-configurations-mavenconfig-2jpk</link>
      <guid>https://dev.to/eliasnogueira/one-of-the-most-underrated-maven-configurations-mavenconfig-2jpk</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Maven is a solid and most used build automation tool in the Java world. Everyone knows Maven!&lt;br&gt;
It’s present in any type of project and one of the first tools we have contact with while learning Java.&lt;/p&gt;

&lt;p&gt;How much do you know about Maven features?&lt;/p&gt;

&lt;p&gt;This is why I will show one of the most underrated Maven Configuration features: the &lt;code&gt;maven.config&lt;/code&gt; file.&lt;/p&gt;
&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;I asked this question on Twitter: How frequently do you use the &lt;code&gt;maven.config&lt;/code&gt; file?&lt;br&gt;
The answer you can see below leads me to think that people don't know about this Maven feature.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1759616561290031497-38" src="https://platform.twitter.com/embed/Tweet.html?id=1759616561290031497"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1759616561290031497-38');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1759616561290031497&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  Maven Configurations
&lt;/h2&gt;

&lt;p&gt;The most common Maven Configurations, that you might use at some point are the command line &lt;code&gt;MVN_OPTS&lt;/code&gt; and &lt;code&gt;MVN_ARGS&lt;/code&gt; environment variables for JVM arguments and Maven options, respectively.&lt;/p&gt;

&lt;p&gt;But there are more! On the &lt;a href="https://maven.apache.org/configure.html" rel="noopener noreferrer"&gt;Maven Configurations&lt;/a&gt; page, you will see the &lt;code&gt;.mvn&lt;/code&gt; directory section that contains explanations about extensions, JVM config, and the Maven config as the &lt;code&gt;.mvn/maven.config&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Maven Config file
&lt;/h2&gt;

&lt;p&gt;It consists of a file that must be placed in a &lt;code&gt;.mvn&lt;/code&gt; folder in the root project directory. Then the &lt;code&gt;maven.config&lt;/code&gt; file can contain all the parameters you commonly pass as arguments.&lt;/p&gt;

&lt;p&gt;Example: When you want to run any command, for example, the test lifecycle, with a quiet output (&lt;code&gt;-q&lt;/code&gt;), using 3 threads (&lt;code&gt;-T3&lt;/code&gt;) and failing it fast (&lt;code&gt;-fail-fast&lt;/code&gt;) you would end up with the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mvn -q -T3 -fail-fast test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be aware of one thing: the configuration in the file is “global” meaning that it will be applied for all the Maven Lifecycles you execute.&lt;/p&gt;

&lt;p&gt;For example, let’s assume you have this configuration in your project and you compile, run the tests, and distribute it in a pipeline, the following commands would be used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compilation process: &lt;code&gt;mvn clean install&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Testing process: &lt;code&gt;mvn test&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Distribution process: &lt;code&gt;mvn install&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that all the commands do not have the &lt;code&gt;-q -T3 -fail-fast&lt;/code&gt;test parameters, but they will be executed anyway because it’s in the &lt;code&gt;.mvn/maven.config&lt;/code&gt; file.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Better Page Objects strategy using AjaxElementLocatorFactory with Selenium and Java</title>
      <dc:creator>Elias Nogueira </dc:creator>
      <pubDate>Wed, 20 Dec 2023 09:50:30 +0000</pubDate>
      <link>https://dev.to/eliasnogueira/better-page-objects-strategy-using-ajaxelementlocatorfactory-with-selenium-and-java-32k8</link>
      <guid>https://dev.to/eliasnogueira/better-page-objects-strategy-using-ajaxelementlocatorfactory-with-selenium-and-java-32k8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Page Objects Model is a Testing Pattern created by Selenium WebDriver to better model the web test architecture into the domain we are testing, creating classes that have all interactions with a web page.&lt;/p&gt;

&lt;p&gt;There are thousands of articles on the internet, and I recommend you view the one from the Selenium WebDriver page: &lt;a href="https://www.selenium.dev/documentation/test_practices/encouraged/page_object_models" rel="noopener noreferrer"&gt;https://www.selenium.dev/documentation/test_practices/encouraged/page_object_models&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Page Factory
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;If you already know about it, please skip this section.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Page Factory is a class that initializes all the elements in the page objects to reduce the class verbosity. Without the usage of the Page Factory class, we would have a class like this:&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;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PageObjectExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&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;public&lt;/span&gt; &lt;span class="nf"&gt;PageObjectExample&lt;/span&gt;&lt;span class="o"&gt;(&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="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;driver&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="o"&gt;}&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;login&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;email&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;password&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;findElement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;By&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="na"&gt;sendKeys&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&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;findElement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;By&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="na"&gt;sendKeys&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&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;findElement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;By&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"next"&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="na"&gt;click&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;p&gt;Note that the method &lt;code&gt;login&lt;/code&gt; has all the interactions with the page, where we are using the &lt;code&gt;driver&lt;/code&gt; field to find and interact within the elements based on its locator.&lt;/p&gt;

&lt;p&gt;This example is fine for a few elements on the page, but I’m sure you will have a lot of elements on some pages.&lt;/p&gt;

&lt;p&gt;Now, what the Page Factory class proposes to do is mainly reduce the verbosity of the Page Object by using WebElements as fields in the class followed by the PageFactory class usage to instantiate the elements.&lt;/p&gt;

&lt;p&gt;This will reduce the necessity to use &lt;code&gt;driver.findElement(By...)&lt;/code&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PageObjectExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@FindBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;WebElement&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@FindBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;WebElement&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@FindBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"next"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;WebElement&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PageObjectExample&lt;/span&gt;&lt;span class="o"&gt;(&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="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;PageFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initElements&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;this&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&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;login&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;email&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;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendKeys&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendKeys&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;click&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;p&gt;You can see on lines 3 to 10, that we are adding each element in the page as a &lt;code&gt;WebElement&lt;/code&gt; field, using the &lt;code&gt;@FindBy&lt;/code&gt; annotation to express its locator.&lt;/p&gt;

&lt;p&gt;On line 13 you can see the usage of the &lt;code&gt;PageFactory&lt;/code&gt; class using the &lt;code&gt;initiElements&lt;/code&gt;, which will, behind the scenes, translate each element into &lt;code&gt;driver.findElement(By...)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On lines 17 to 19, you can see the usage of the element itself without the &lt;code&gt;driver.findElement(By…)&lt;/code&gt; because it was already one by the &lt;code&gt;PageFactory&lt;/code&gt; class. This reduces the amount of code and verbosity you would possibly have.&lt;/p&gt;

&lt;p&gt;Please, also read this definition of Page Factory from the SeleniumHQ wiki: &lt;a href="https://github.com/SeleniumHQ/selenium/wiki/PageFactory" rel="noopener noreferrer"&gt;https://github.com/SeleniumHQ/selenium/wiki/PageFactory&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The common problem during the Page Objects modeling
&lt;/h2&gt;

&lt;p&gt;The main problem is the element &lt;strong&gt;wait strategy&lt;/strong&gt;. For instance, we have three different ones in Selenium WebDriver and the recommended ones are the &lt;a href="https://www.selenium.dev/documentation/webdriver/waits/#explicit-wait" rel="noopener noreferrer"&gt;Explicitly Wait&lt;/a&gt; and the &lt;a href="https://www.selenium.dev/documentation/webdriver/waits/#fluentwait" rel="noopener noreferrer"&gt;Fluent Wait&lt;/a&gt;. The &lt;a href="https://www.selenium.dev/documentation/webdriver/waits/#implicit-wait" rel="noopener noreferrer"&gt;Implicitly Wait&lt;/a&gt; is, nowadays, considered a bad practice.&lt;/p&gt;

&lt;p&gt;We have two main cases to apply a waiting strategy in the Page Objects: in the class constructor or the action methods.&lt;/p&gt;

&lt;p&gt;Just a heads-up: we only use either Explicitly or Fluent Waits when necessary. Not for any action, we create!&lt;/p&gt;

&lt;h3&gt;
  
  
  Wait for an element in the constructor
&lt;/h3&gt;

&lt;p&gt;Normally this approach is used when you need to make sure the main element you will interact with is loaded into the page. You could replace this with the wait in the action method, of course, but this approach “tells” you explicitly that you are waiting for the element before proceeding with all the actions.&lt;/p&gt;

&lt;p&gt;This is a simple example:&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;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PageObjectExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&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="nd"&gt;@FindBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;WebElement&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@FindBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;WebElement&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@FindBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"next"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;WebElement&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PageObjectExample&lt;/span&gt;&lt;span class="o"&gt;(&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="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;driver&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="nc"&gt;PageFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initElements&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;this&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebDriverWait&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="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ChronoUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SECONDS&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;until&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ExpectedConditions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;visibilityOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&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;login&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;email&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;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendKeys&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendKeys&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;click&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;p&gt;Note that, on lines 18 and 19, there’s an Explicitly Wait waiting until the email field is visible on the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wait for an element in the action methods
&lt;/h3&gt;

&lt;p&gt;When an element that you are about to interact with is not present/visible/clickable we add an Explicitly Wait to make sure test integrity. We simply add an Explicitly Wait before the real action.&lt;/p&gt;

&lt;p&gt;This is a simple example:&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;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PageObjectExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&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="nd"&gt;@FindBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;WebElement&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@FindBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;WebElement&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@FindBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"next"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;WebElement&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PageObjectExample&lt;/span&gt;&lt;span class="o"&gt;(&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="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;PageFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initElements&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;this&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&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;fillEmail&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;email&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebDriverWait&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="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ChronoUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SECONDS&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;until&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ExpectedConditions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;visibilityOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendKeys&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&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;p&gt;You can see in lines 19 to 20, that we are waiting for the &lt;code&gt;email&lt;/code&gt; field to be visible before filling in a value on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to reduce verbosity for the PageFactory and Waiting strategy
&lt;/h2&gt;

&lt;p&gt;We can use two techniques:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the &lt;code&gt;AjaxElementLocatorFactory&lt;/code&gt; in the P&lt;code&gt;ageFactory.initiElements&lt;/code&gt; to apply an automatic explicit wait&lt;/li&gt;
&lt;li&gt;Use the inheritance to avoid duplicated code for the &lt;code&gt;PageFactory.initiElements&lt;/code&gt; usage&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What’s the AjaxElementLocatorFactory
&lt;/h3&gt;

&lt;p&gt;This class in Selenium WebDriver adds a lazy load approach in the Page Factory class. It uses an Explicitly Wait when loading the element, which means when we use it, for at least de defined time you will express.&lt;/p&gt;

&lt;p&gt;The usage of this class will reduce the necessity of explicitly waiting for elements in most cases. Of course, you might face cases where you need to add an Explicitly wait.&lt;/p&gt;

&lt;p&gt;The regular code within the combination of the PageFactory class will look like this:&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;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PageObjectExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&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;// WebElements ignored&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PageObjectExample&lt;/span&gt;&lt;span class="o"&gt;(&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="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;PageFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initElements&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;AjaxElementLocatorFactory&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="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="k"&gt;this&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;p&gt;You can see that we are instantiating the &lt;code&gt;AjaxElementLocatorFactory&lt;/code&gt; inside of the &lt;code&gt;PageFactory.initElements&lt;/code&gt;. This class needs the driver instance and the timeout in seconds.&lt;/p&gt;

&lt;p&gt;This would be added in each Page Object class you have, but we have a better way to avoid it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using inheritance in our favor
&lt;/h4&gt;

&lt;p&gt;Instead of adding this code snippet to each Page Object, we can create an abstract class to handle this job.&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;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AbstractPageObject&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&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="nf"&gt;AbstractPageObject&lt;/span&gt;&lt;span class="o"&gt;(&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="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;PageFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initElements&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;AjaxElementLocatorFactory&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="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="k"&gt;this&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;p&gt;Note we have an abstract class that will init the elements for the provided driver instance, adding the &lt;code&gt;AjaxElementLocatorFactory&lt;/code&gt; and waiting until 5 seconds for the element, if necessary.&lt;/p&gt;

&lt;p&gt;Now we need to extend it in the Page Object class, adopting the constructor and invoking &lt;code&gt;super&lt;/code&gt; to use the one from the abstract class:&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;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PageObject&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractPageObject&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// WebElements ignored&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nf"&gt;PageObject&lt;/span&gt;&lt;span class="o"&gt;(&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="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&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="o"&gt;}&lt;/span&gt;

   &lt;span class="c1"&gt;// action steps ignored&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Concrete example
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://github.com/eliasnogueira/selenium-java-lean-test-architecture" rel="noopener noreferrer"&gt;selenium-java-lean-test-architecture&lt;/a&gt; project you can see the following implemented structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The class &lt;a href="https://github.com/eliasnogueira/selenium-java-lean-test-architecture/blob/master/src/main/java/com/eliasnogueira/page/AbstractPageObject.java" rel="noopener noreferrer"&gt;AbstractPageObject&lt;/a&gt; has the Page Object initialization within the &lt;code&gt;AjaxElementLocatorFactory&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The driver inside the &lt;code&gt;AbstractPageObject&lt;/code&gt; is managed by the &lt;a href="https://github.com/eliasnogueira/selenium-java-lean-test-architecture/blob/master/src/main/java/com/eliasnogueira/driver/DriverManager.java" rel="noopener noreferrer"&gt;DriverManager&lt;/a&gt; class which creates a thread instance to guarantee the parallel execution&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;AbstractPageObject&lt;/code&gt; class is being used in the &lt;a href="https://github.com/eliasnogueira/selenium-java-lean-test-architecture/blob/master/src/main/java/com/eliasnogueira/page/booking/common/NavigationPage.java" rel="noopener noreferrer"&gt;NavigationPage&lt;/a&gt;. Note that we don’t have the constructor using the super to send the driver instance as the &lt;code&gt;DriverManager&lt;/code&gt; is taking care of the driver&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://github.com/eliasnogueira/selenium-java-lean-test-architecture/tree/master/src/main/java/com/eliasnogueira/page/booking" rel="noopener noreferrer"&gt;other page object&lt;/a&gt; classes are using the &lt;code&gt;NavigationPage&lt;/code&gt;, so indirectly they are also using the &lt;code&gt;AbstractPageObject&lt;/code&gt; class&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>testing</category>
      <category>selenium</category>
      <category>testautomation</category>
    </item>
    <item>
      <title>The best way to create browser instances using the Factory Pattern, Java, and Selenium WebDriver</title>
      <dc:creator>Elias Nogueira </dc:creator>
      <pubDate>Sat, 20 Aug 2022 09:41:19 +0000</pubDate>
      <link>https://dev.to/eliasnogueira/the-best-way-to-create-browser-instances-using-the-factory-pattern-java-and-selenium-webdriver-16l5</link>
      <guid>https://dev.to/eliasnogueira/the-best-way-to-create-browser-instances-using-the-factory-pattern-java-and-selenium-webdriver-16l5</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This article belongs to a series of 3 posts explaining how to use the Factory Pattern to create different browser instances for either local or remote execution using Selenium WebDriver.&lt;/p&gt;

&lt;p&gt;You can find the following previous article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.eliasnogueira.com/how-to-use-the-factory-design-pattern-to-create-browser-instances-the-simple-approach/" rel="noopener noreferrer"&gt;How to use the Factory design pattern to create browser instances: the simple approach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.eliasnogueira.com/how-to-use-the-factory-design-pattern-to-create-browser-instances-local-and-remote-approach/" rel="noopener noreferrer"&gt;How to use the Factory design pattern to create browser instances: local and remote approach&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This one will refer to some explanations and code from the previous one, but don’t be afraid, you will understand everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  General explanation
&lt;/h2&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%2F7x9r3fpotgjnp8g7zz61.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%2F7x9r3fpotgjnp8g7zz61.png" alt=" " width="791" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Can you imagine you can implement a good approach to create multiple browser instances with only two classes?&lt;/p&gt;

&lt;h3&gt;
  
  
  The BrowserFactory and the power of enums
&lt;/h3&gt;

&lt;p&gt;We already know that the &lt;a href="https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html" rel="noopener noreferrer"&gt;Enum Types&lt;/a&gt; have constant and can have methods.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;BrowserFactory&lt;/code&gt; class is an enum with the list of supported browsers (constants) for the implementation I’ve created: Chrome, Firefox, Edge, and Safari.&lt;/p&gt;

&lt;p&gt;We can add an extra function on this enum with methods, but instead of creating the regular ones we will make each constant implement two methods: &lt;code&gt;createDriver()&lt;/code&gt; for the local execution and &lt;code&gt;getOptions()&lt;/code&gt; for the remote execution. In order to do so, we must implement abstract methods inside the enum. Take a look at the example:&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;public&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;BrowserFactory&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="no"&gt;CHROME&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;@Override&lt;/span&gt;
        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;WebDriver&lt;/span&gt; &lt;span class="nf"&gt;createDriver&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;WebDriverManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DriverManagerType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CHROME&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ChromeDriver&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getOptions&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nd"&gt;@Override&lt;/span&gt;
        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ChromeOptions&lt;/span&gt; &lt;span class="nf"&gt;getOptions&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;ChromeOptions&lt;/span&gt; &lt;span class="n"&gt;chromeOptions&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;ChromeOptions&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;chromeOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addArguments&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"--start-maximized"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;chromeOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addArguments&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"--disable-infobars"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;chromeOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addArguments&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"--disable-notifications"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;chromeOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setHeadless&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;headless&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;chromeOptions&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="nc"&gt;WebDriver&lt;/span&gt; &lt;span class="nf"&gt;createDriver&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;abstract&lt;/span&gt; &lt;span class="nc"&gt;AbstractDriverOptions&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getOptions&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;p&gt;On lines 23 and 24 we have two abstract methods. Each enum constant needs to implement the abstract method.&lt;/p&gt;

&lt;p&gt;On lines 5 to 9, there’s the implementation of the &lt;code&gt;createDriver()&lt;/code&gt; method creating a local browser instance using the &lt;a href="https://github.com/bonigarcia/webdrivermanager" rel="noopener noreferrer"&gt;WebDriverManager&lt;/a&gt; library. Note that the new browser instance is using the &lt;code&gt;getOptions()&lt;/code&gt; and I will explain it in a minute.&lt;/p&gt;

&lt;p&gt;You can see that line 24 has the &lt;a href="https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/remote/AbstractDriverOptions.html" rel="noopener noreferrer"&gt;AbstractDriverOptions&lt;/a&gt; with an unknown generic, placed with &lt;code&gt;?&lt;/code&gt; as the wildcard. It returns this class because each internal Selenium WebDriver remote browser implementation extends this class, making it easier to set the correct object for the remote instance creation. You can see this by accessing the AbstractDriverOptions Javadoc in the section “Direct Known Subclasses“&lt;/p&gt;

&lt;p&gt;Lines 12 to 20 show the specific &lt;code&gt;ChromeOptions&lt;/code&gt; we must set for the remote execution, as the remote class is called “option” which must be set.&lt;/p&gt;

&lt;p&gt;And why we have the &lt;code&gt;getOptions()&lt;/code&gt; method being used in the &lt;code&gt;createDriver()&lt;/code&gt;? To automatically set any option we want to. The option classes do not need the browser driver set as needed in the local execution.&lt;/p&gt;

&lt;p&gt;The full BrowserDriver implementation can be found at &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/master/src/main/java/com/eliasnogueira/driver/BrowserFactory.java" rel="noopener noreferrer"&gt;https://github.com/eliasnogueira/selenium-java-browser-factory/blob/master/src/main/java/com/eliasnogueira/driver/BrowserFactory.java&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The DriverFactory class
&lt;/h3&gt;

&lt;p&gt;This class is responsible to manage the local or remote instances because we need different code approaches using Selenium WebDriver. We have two main methods: the &lt;code&gt;createInstance()&lt;/code&gt; for the local execution and the &lt;code&gt;createRemoveInstance()&lt;/code&gt; for the remote execution.&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating the local instance
&lt;/h4&gt;

&lt;p&gt;The local instance means that we will run the tests locally in the browser installed on the machine.&lt;/p&gt;

&lt;p&gt;The method &lt;code&gt;createInstance()&lt;/code&gt; has the browser as the method parameter that the &lt;code&gt;BaseTest&lt;/code&gt; class will use to determine which browser will be instantiated.&lt;/p&gt;

&lt;p&gt;The browser value attribute is transformed in the &lt;code&gt;Target&lt;/code&gt; enum and then used in the switch-case.&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;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DriverFactory&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;WebDriver&lt;/span&gt; &lt;span class="nf"&gt;createInstance&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="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Target&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toUpperCase&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="nc"&gt;WebDriver&lt;/span&gt; &lt;span class="n"&gt;webdriver&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;target&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="nl"&gt;LOCAL:&lt;/span&gt;
                &lt;span class="n"&gt;webdriver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BrowserFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&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="na"&gt;toUpperCase&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;createDriver&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="nl"&gt;REMOTE:&lt;/span&gt;
                &lt;span class="n"&gt;webdriver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createRemoteInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BrowserFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&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="na"&gt;toUpperCase&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;getOptions&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;TargetNotValidException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;webdriver&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;p&gt;When the target is &lt;code&gt;LOCAL&lt;/code&gt; the &lt;code&gt;BrowserFactory&lt;/code&gt; class will call the &lt;code&gt;createDriver()&lt;/code&gt; method for the browser we have set. This approach removes the necessity to have the &lt;code&gt;switch-case&lt;/code&gt; for each browser as the browser value will be transformed in the enum constant. Less code, more readable code!&lt;/p&gt;

&lt;p&gt;You can see this happening on lines 8 to 10.&lt;/p&gt;

&lt;p&gt;Remember that the browser to use locally is set in the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/master/src/test/resources/general.properties#L2" rel="noopener noreferrer"&gt;general.properties&lt;/a&gt; class.&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating the Remote instance
&lt;/h4&gt;

&lt;p&gt;It works similar to the local approach when the code determines if the execution is local or remote. Line 12, in the previous code snippet, shows that the &lt;code&gt;BrowserFactory&lt;/code&gt; will call the &lt;code&gt;getOptions()&lt;/code&gt; method based on the browser we have set. With this, we have the browser options object. Now it’s time to create the real remote instance.&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;private&lt;/span&gt; &lt;span class="nc"&gt;RemoteWebDriver&lt;/span&gt; &lt;span class="nf"&gt;createRemoteInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MutableCapabilities&lt;/span&gt; &lt;span class="n"&gt;capability&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;RemoteWebDriver&lt;/span&gt; &lt;span class="n"&gt;remoteWebDriver&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="k"&gt;try&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;gridURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://%s:%s"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;gridUrl&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;gridPort&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="n"&gt;remoteWebDriver&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;RemoteWebDriver&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gridURL&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;capability&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="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MalformedURLException&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;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Level&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SEVERE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Grid URL is invalid or Grid is not available"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Level&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SEVERE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Browser: %s"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capability&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBrowserName&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="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IllegalArgumentException&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;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Level&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SEVERE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Browser %s is not valid or recognized"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capability&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBrowserName&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;remoteWebDriver&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;p&gt;The &lt;code&gt;createRemoteInstance()&lt;/code&gt; method expects a &lt;code&gt;MutableCapability&lt;/code&gt; object, which is the same as the browser option object because the &lt;a href="https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/remote/AbstractDriverOptions.html" rel="noopener noreferrer"&gt;AbstractDriverOptions&lt;/a&gt; extends the &lt;a href="https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/MutableCapabilities.html" rel="noopener noreferrer"&gt;MutableCapabilities&lt;/a&gt; class.&lt;/p&gt;

&lt;p&gt;To create a remote browser instance we must use the &lt;code&gt;RemoteWebDriver&lt;/code&gt; class, adding as a parameter the target remote machine (or a grid) and the capability, which is the browser with the options.&lt;/p&gt;

&lt;p&gt;On line 4 the URL for the remote machine is created based on the information we have in the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/master/src/main/resources/grid.properties" rel="noopener noreferrer"&gt;grid.properties&lt;/a&gt; file. On line 6 the remote instance is created. The rest of the code is the exception handler, necessary to know what happened if any problem occurs during the remote instance creation.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to associate this with the test?
&lt;/h3&gt;

&lt;p&gt;First, it’s a good practice to have a BaseTest class managing the general pre and post-conditions. The &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/master/src/test/java/com/eliasnogueira/BaseWeb.java" rel="noopener noreferrer"&gt;BaseWeb&lt;/a&gt; class has the pre-conditions, as a JUnit &lt;code&gt;@BeforeEach&lt;/code&gt; annotation, the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Line 8: getting the configurations, which means all the information from the properties file&lt;/li&gt;
&lt;li&gt;Line 10: the creation of the browser instance based on the browser set in the properties file&lt;/li&gt;
&lt;li&gt;Line 11: setting the URL to start the test
&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseWeb&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="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;Configuration&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@BeforeEach&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;preCondition&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;configuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configuration&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;DriverFactory&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;createInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;browser&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;configuration&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&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;@AfterEach&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;postCondition&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main part related to this approach is in line 10, where the &lt;code&gt;DriverFactory&lt;/code&gt; class will know, internally, if the execution is local or remote based on the value set for the &lt;code&gt;target&lt;/code&gt; property set in the &lt;code&gt;general.properties&lt;/code&gt; file. The browser was also set in this file but through the &lt;code&gt;browser&lt;/code&gt; property will be used to create the local browser instance or the remote instance.&lt;/p&gt;

&lt;p&gt;The tests must extends the &lt;code&gt;BaseWeb&lt;/code&gt; to work properly.&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;class&lt;/span&gt; &lt;span class="nc"&gt;BookRoomWebTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseWeb&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;bookARoom&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;navigate&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s"&gt;"how-to-create-lean-test-automation-architecture-for-web-using-java-libraries"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;assertThat&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;findElement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;By&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cssSelector&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;".hestia-title.title-in-content"&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="na"&gt;getText&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;
                &lt;span class="n"&gt;isEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"How to create Lean Test Automation Architecture for Web using Java libraries"&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;
  
  
  How to run this project in remote machines
&lt;/h2&gt;

&lt;p&gt;If you would like to give it a try the complete project &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory" rel="noopener noreferrer"&gt;selenium-java-browser-factory&lt;/a&gt; has a docker-compose file that will start a Selenium 4 Grid with Chrome, Firefox, and Edge browsers. So you will be able to run remote instances.&lt;/p&gt;

&lt;p&gt;To exercise this, please follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start Docker&lt;/li&gt;
&lt;li&gt;Navigate, through your Command-Line/Terminal app to the project root folder&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;docker-compose up&lt;/code&gt; command&lt;/li&gt;
&lt;li&gt;Access &lt;code&gt;http://localhost:4444&lt;/code&gt; to see the Selenium Grid page with the browsers available (Chrome, Edge, and Firefox)&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;general.properties&lt;/code&gt; file, change the &lt;code&gt;target&lt;/code&gt; attribute value to &lt;code&gt;remote&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;code&gt;grid.properties&lt;/code&gt; file in &lt;code&gt;src/main/java/resources&lt;/code&gt; already have the values to connect to a local grid&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Run the &lt;code&gt;BookARoomWebTest&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;you can go to the Selenium Grid dashboard and click on the Sessions tab&lt;/li&gt;
&lt;li&gt;as soon as the test starts a session related to the browser in use will be listed&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The complete example
&lt;/h2&gt;

&lt;p&gt;You can navigate to the following GitHub repo to see a complete and functional example in the branch &lt;code&gt;local-remote-example&lt;/code&gt;. Spare some time to look at the new classes added and understand how it was structured.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/tree/basic-example" rel="noopener noreferrer"&gt;https://github.com/eliasnogueira/selenium-java-browser-factory/tree/basic-example&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>java</category>
      <category>webtesting</category>
      <category>selenium</category>
    </item>
    <item>
      <title>How to use the Factory design pattern to create browser instances: local and remote approach</title>
      <dc:creator>Elias Nogueira </dc:creator>
      <pubDate>Mon, 20 Jun 2022 14:53:15 +0000</pubDate>
      <link>https://dev.to/eliasnogueira/how-to-use-the-factory-design-pattern-to-create-browser-instances-local-and-remote-approach-bjm</link>
      <guid>https://dev.to/eliasnogueira/how-to-use-the-factory-design-pattern-to-create-browser-instances-local-and-remote-approach-bjm</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;In the previous article [How to use the Factory design pattern to create browser instances: the simple approach&lt;br&gt;
(&lt;a href="http://www.eliasnogueira.com/how-to-use-the-factory-design-pattern-to-create-browser-instances-the-simple-approach/" rel="noopener noreferrer"&gt;http://www.eliasnogueira.com/how-to-use-the-factory-design-pattern-to-create-browser-instances-the-simple-approach/&lt;/a&gt;), you have learned how to implement it. I’ve named it “simple” because the code created runs only locally, which is the simplest and most elegant way of using Java to do it.&lt;/p&gt;
&lt;h1&gt;
  
  
  Code explanation
&lt;/h1&gt;

&lt;p&gt;To make this post/tutorial as short as possible I will refer, through links, to the existing code implementation where you can access and understand more about the solution applied.&lt;/p&gt;
&lt;h1&gt;
  
  
  Difference between local and remote execution
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Local execution&lt;/strong&gt; means the usage of the browser installed on the same machine you will run the tests, so we need the web browser and the browser drivers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remote execution&lt;/strong&gt; means the execution of the tests in a different machine from the one you will trigger. This “machine” is actually any resource as a different real machine (bare-metal), a Docker container, or a remote service (E.g: SauceLabs, BrowserStack).&lt;/p&gt;
&lt;h2&gt;
  
  
  The technical differences in Selenium
&lt;/h2&gt;

&lt;p&gt;In the &lt;strong&gt;local execution&lt;/strong&gt;, we directly use the browser instance. Don’t forget you need also the browser driver and it can be easily configured using the &lt;a href="//The%20technical%20differences%20in%20Selenium&amp;lt;br&amp;gt;%0AIn%20the%20local%20execution,%20we%20directly%20use%20the%20browser%20instance.%20Don%E2%80%99t%20forget%20you%20need%20also%20the%20browser%20driver%20and%20it%20can%20be%20easily%20configured%20using%20the%20WebDriverManager%20library."&gt;WebDriverManager&lt;/a&gt; library.&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="c1"&gt;// setting up the browser driver with the WebDriverManager library&lt;/span&gt;
&lt;span class="nc"&gt;WebDriverManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;CHROME&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// creating the local browser instance&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ChromeDriver&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The WebDriverManager will set up the Chrome driver and Selenium will look a the local Google Chrome installation and will use it to run your tests.&lt;/p&gt;

&lt;p&gt;But, for the &lt;strong&gt;remote execution&lt;/strong&gt;, things are a little bit different. You will need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;have the target machine URL&lt;/li&gt;
&lt;li&gt;use the &lt;a href="https://www.selenium.dev/documentation/webdriver/remote_webdriver/" rel="noopener noreferrer"&gt;RemoteWebDriver&lt;/a&gt; class, instead of the browser class with the following parameters:

&lt;ul&gt;
&lt;li&gt;the URL for the target machine&lt;/li&gt;
&lt;li&gt;the “capability” to run&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Code organization
&lt;/h1&gt;

&lt;p&gt;Similar to the &lt;a href="http://www.eliasnogueira.com/how-to-use-the-factory-design-pattern-to-create-browser-instances-the-simple-approach/" rel="noopener noreferrer"&gt;How to use the Factory design pattern to create browser instances: the simple approach&lt;/a&gt; article shows how to create a factory class to manage different browsers to run locally, we have now to create a way to determine when to run locally and when to run in a remote machine.&lt;/p&gt;

&lt;p&gt;This is the class diagram that we will work on.&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%2Fy7vcieb0daqwi9n6puwh.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%2Fy7vcieb0daqwi9n6puwh.png" alt="Class diagram" width="800" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Diagram explanation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  manager package
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;IDriveManager&lt;/code&gt; is an interface that has the methods to implement in the manager classes. The manager classes have the implementation for the local, and now, remote execution.&lt;br&gt;
The local execution is done by the method &lt;code&gt;createDriver()&lt;/code&gt; and the remote execution is done by the &lt;code&gt;getOptions()&lt;/code&gt; method. I will explain more about it later.&lt;/p&gt;
&lt;h3&gt;
  
  
  driver package
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;DriverFactory&lt;/code&gt; class is the one responsible to know if the execution will be either local or remote. We manage this through a property value. Based on the target environment we will instantiate either the &lt;code&gt;LocalDriverFactory&lt;/code&gt; or the &lt;code&gt;RemoteDriverFactory&lt;/code&gt;. This class implemented the interface &lt;code&gt;IDriverFactory&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  factory package
&lt;/h3&gt;

&lt;p&gt;The LocalDriverFactory class is responsible to create the local browser instance using the &lt;code&gt;createDriver()&lt;/code&gt; method from the manager classes.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;RemoteDriverFactory&lt;/code&gt; class is responsible to create the remote browser execution using the &lt;code&gt;getOptions()&lt;/code&gt; from the manager classes. The internal private method &lt;code&gt;createRemoteInstance()&lt;/code&gt; will connect to the remote machine before the creation of the browser instance.&lt;/p&gt;
&lt;h1&gt;
  
  
  Implementation
&lt;/h1&gt;

&lt;p&gt;I will explain here how to evolve code based on the simple approach. The following sub-items will explain it.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Manager the local and remote execution
&lt;/h2&gt;
&lt;h3&gt;
  
  
  New properties
&lt;/h3&gt;

&lt;p&gt;The first thing we need to create is a way to run the test using either a local or remote machine. For the remote execution, we will need to parameterize the URL and port we will connect our tests. We also need to add a way to say when we need to execute it as local or remote.&lt;/p&gt;

&lt;p&gt;The approach I’ve created is to add a new &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/main/resources/grid.properties" rel="noopener noreferrer"&gt;grid.properties&lt;/a&gt; file to add the Selenium Grid URL and port&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# grid url and port
grid.url = localhost
grid.port = 4444
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: the file is named grid, as well as the properties because the way to run Selenium tests in different machines implies the Selenium Grid features.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We also need to update the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/test/resources/general.properties" rel="noopener noreferrer"&gt;general.properties&lt;/a&gt; file to have the local property to tell, somehow, we can execute it locally or remote. Line 2 shows the new property.&lt;/p&gt;

&lt;p&gt;Finally, in the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/main/java/com/eliasnogueira/config/Configuration.java#L35-L53" rel="noopener noreferrer"&gt;Configuration class&lt;/a&gt;, you will see the new association to the new properties created in the &lt;code&gt;gird.properties&lt;/code&gt; and &lt;code&gt;general.properties&lt;/code&gt;. Also the load of the grid.properties in the &lt;code&gt;@Config.Sources&lt;/code&gt; annotation from the Owner library.&lt;/p&gt;

&lt;h3&gt;
  
  
  New class to manage the local and remote execution
&lt;/h3&gt;

&lt;p&gt;The previous DriverFactory was managing the local execution. Now, to maintain a better naming consistency, we are changing it to manage the execution into local or remote. It has a simple switch-case to instantiate the correct internal class.&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;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DriverFactory&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;IDriverFactory&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;WebDriver&lt;/span&gt; &lt;span class="nf"&gt;createInstance&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="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Target&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toUpperCase&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="nc"&gt;WebDriver&lt;/span&gt; &lt;span class="n"&gt;webdriver&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;target&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="nl"&gt;LOCAL:&lt;/span&gt;
                &lt;span class="n"&gt;webdriver&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;LocalDriverFactory&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;createInstance&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="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="nl"&gt;REMOTE:&lt;/span&gt;
                &lt;span class="n"&gt;webdriver&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;RemoteDriverFactory&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;createInstance&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="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;TargetNotValidException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Target&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;LOCAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;REMOTE&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;p&gt;Lines 21 to 23 show an internal enum named &lt;code&gt;Target&lt;/code&gt; which has &lt;code&gt;LOCAL&lt;/code&gt; and &lt;code&gt;REMOTE&lt;/code&gt; as possible values.&lt;/p&gt;

&lt;p&gt;Line 5 loads the target property from the &lt;code&gt;general.properties&lt;/code&gt; file and converts it to &lt;code&gt;Target&lt;/code&gt; enum, whereas line 8 applies a switch statement in the enum.&lt;/p&gt;

&lt;p&gt;When the execution is from the local, the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/main/java/com/eliasnogueira/driver/factory/LocalDriverFactory.java" rel="noopener noreferrer"&gt;LocalDriverFactory&lt;/a&gt; class is in use to create the &lt;code&gt;WebDriver&lt;/code&gt; instance based on the browser set in &lt;code&gt;general.properties&lt;/code&gt; file. When the execution is remote the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/main/java/com/eliasnogueira/driver/factory/RemoteDriverFactory.java" rel="noopener noreferrer"&gt;RemoteDriverFactory&lt;/a&gt; class is in use. The &lt;code&gt;LocalDriverFactory&lt;/code&gt; class is the same as the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/basic-example/src/main/java/com/eliasnogueira/driver/factory/DriverFactory.java" rel="noopener noreferrer"&gt;previous DriverFactory from the basic-example branch&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  New LocalDriverFactory
&lt;/h3&gt;

&lt;p&gt;This class is identical to the previous &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/basic-example/src/main/java/com/eliasnogueira/driver/factory/DriverFactory.java" rel="noopener noreferrer"&gt;DriverFactory&lt;/a&gt;. You can take a look at the implemented &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/main/java/com/eliasnogueira/driver/factory/LocalDriverFactory.java" rel="noopener noreferrer"&gt;LocalDriverFactory&lt;/a&gt; class.&lt;/p&gt;

&lt;h3&gt;
  
  
  New RemoteDriverFactory class
&lt;/h3&gt;

&lt;p&gt;We now have a new class to instantiate the different browsers for the remote execution. I will assume here you are already familiar with Selenium Grid, so I will skip the explanation of the code that creates the &lt;code&gt;RemoteWebDriverInstance&lt;/code&gt;. If you need to learn more about it, please read the official &lt;a href="https://www.selenium.dev/documentation/grid/" rel="noopener noreferrer"&gt;Selenium Grid documentation&lt;/a&gt; and the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/main/java/com/eliasnogueira/driver/factory/RemoteDriverFactory.java#L72-L86" rel="noopener noreferrer"&gt;code I’ve implemented&lt;/a&gt; for this solution.&lt;/p&gt;

&lt;p&gt;Basically, we will have the same &lt;code&gt;switch-case&lt;/code&gt; strategy for each browser compared to the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/main/java/com/eliasnogueira/driver/factory/LocalDriverFactory.java" rel="noopener noreferrer"&gt;LocalDriverFactory&lt;/a&gt;, but instead of instantiating the local browser, we need to instantiate the remote one.&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="nd"&gt;@Override&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;WebDriver&lt;/span&gt; &lt;span class="nf"&gt;createInstance&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="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;MutableCapabilities&lt;/span&gt; &lt;span class="n"&gt;capability&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;BrowserList&lt;/span&gt; &lt;span class="n"&gt;browserToCreate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BrowserList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&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="na"&gt;toUpperCase&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;browserToCreate&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="nl"&gt;CHROME:&lt;/span&gt;
            &lt;span class="n"&gt;capability&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;ChromeDriverManager&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getOptions&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="nl"&gt;FIREFOX:&lt;/span&gt;
            &lt;span class="n"&gt;capability&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;FirefoxDriverManager&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getOptions&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="nl"&gt;EDGE:&lt;/span&gt;
            &lt;span class="n"&gt;capability&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;EdgeDriverManager&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getOptions&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="nl"&gt;SAFARI:&lt;/span&gt;
            &lt;span class="n"&gt;capability&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;SafariDriverManager&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getOptions&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;BrowserNotSupportedException&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="s"&gt;"is not supported!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;createRemoteInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;capability&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;p&gt;Note that the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/main/java/com/eliasnogueira/driver/factory/RemoteDriverFactory.java#L47-L70" rel="noopener noreferrer"&gt;RemoteDriverFactory&lt;/a&gt; class is now using the &lt;code&gt;getOptions()&lt;/code&gt; method instead of the &lt;code&gt;createDriver()&lt;/code&gt; from each &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/tree/local-remote-example/src/main/java/com/eliasnogueira/driver/factory/manager" rel="noopener noreferrer"&gt;manager driver class&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Additional getOptions() method in the driver manager classes
&lt;/h2&gt;

&lt;p&gt;Each driver manager class will have, additionally, a new method to use when the execution is remote. As the &lt;code&gt;RemoteWebDriver&lt;/code&gt; does not accept a browser instance directly, but a &lt;a href="https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/MutableCapabilities.html" rel="noopener noreferrer"&gt;MutableCapabilities&lt;/a&gt; class, we need to specify the correlated option class of the browser.&lt;/p&gt;

&lt;p&gt;Each browser has its own &lt;code&gt;*Options&lt;/code&gt; class, like &lt;a href="https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/chrome/ChromeOptions.html" rel="noopener noreferrer"&gt;ChromeOptions&lt;/a&gt;, &lt;a href="https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/firefox/FirefoxOptions.html" rel="noopener noreferrer"&gt;FirefoxOptions&lt;/a&gt;, and so on. Those classes exist for the remote execution and have pre-configured options as their identification plus methods that can extend their features. Internally the &lt;code&gt;*Options&lt;/code&gt; classes have a hierarchy dependency on the &lt;code&gt;MutableCapabilities&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;What we need to do is to add the &lt;code&gt;getOptions()&lt;/code&gt; methods to each &lt;code&gt;DriverManager&lt;/code&gt; class. This method must instantiate the related browser option and can add more features.&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="nd"&gt;@Override&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ChromeOptions&lt;/span&gt; &lt;span class="nf"&gt;getOptions&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;ChromeOptions&lt;/span&gt; &lt;span class="n"&gt;chromeOptions&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;ChromeOptions&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;chromeOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addArguments&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"--start-maximized"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;chromeOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addArguments&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"--disable-infobars"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;chromeOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addArguments&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"--disable-notifications"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;chromeOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setHeadless&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;headless&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;chromeOptions&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;p&gt;The code above shows the &lt;code&gt;getOptions()&lt;/code&gt; method for the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/main/java/com/eliasnogueira/driver/factory/manager/ChromeDriverManager.java" rel="noopener noreferrer"&gt;ChromeDriverManager&lt;/a&gt; class where we are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;creating an instance of its option on line 3&lt;/li&gt;
&lt;li&gt;adding additional arguments to the browser on lines 4 to 6&lt;/li&gt;
&lt;li&gt;setting it as headless based on the headless configuration value present in the &lt;code&gt;general.properties&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;returning the object instantiated to be used as the &lt;code&gt;RemoteWebDriver&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see all the implemented &lt;code&gt;DriverManager&lt;/code&gt; classes in the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/tree/local-remote-example/src/main/java/com/eliasnogueira/driver/factory/manager" rel="noopener noreferrer"&gt;manager package&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to run
&lt;/h1&gt;

&lt;p&gt;The execution to local or remote will is based on the &lt;code&gt;target&lt;/code&gt; property value in the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/test/resources/general.properties#L2" rel="noopener noreferrer"&gt;general.properties&lt;/a&gt; file. We know that when the execution is &lt;code&gt;local&lt;/code&gt; the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/main/java/com/eliasnogueira/driver/DriverFactory.java" rel="noopener noreferrer"&gt;DriverFactory&lt;/a&gt; will use the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/main/java/com/eliasnogueira/driver/factory/LocalDriverFactory.java" rel="noopener noreferrer"&gt;LocalDriverFactory&lt;/a&gt; class to create the local browser instance and when the execution is &lt;code&gt;remote&lt;/code&gt; the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/main/java/com/eliasnogueira/driver/DriverFactory.java" rel="noopener noreferrer"&gt;DriverFactory&lt;/a&gt; will use the &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/src/main/java/com/eliasnogueira/driver/factory/RemoteDriverFactory.java" rel="noopener noreferrer"&gt;RemoteDriverFactory&lt;/a&gt; to create a remote browser instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running it locally
&lt;/h2&gt;

&lt;p&gt;Follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;code&gt;general.properties&lt;/code&gt; file located in &lt;code&gt;src/test/java/resources&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Change the &lt;code&gt;target&lt;/code&gt; property value to &lt;code&gt;local&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Change the &lt;code&gt;browser&lt;/code&gt; property value to any browser you have installed&lt;/li&gt;
&lt;li&gt;Run the &lt;code&gt;BookARoomWebTest&lt;/code&gt; class&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The expected result is the test being executed in your local machine for your set browser. This is the same way we did in the previous post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running it in a remote machine
&lt;/h2&gt;

&lt;p&gt;Now things get more interesting. We need to find a way to execute the test on a remote machine. As written before a remote machine can be a physical or virtual machine existent in your network or a cloud provider. To be able to run it on your machine right now the Docker is one of your best choices.&lt;/p&gt;

&lt;p&gt;The project has a &lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/blob/local-remote-example/docker-compose.yml" rel="noopener noreferrer"&gt;docker-compose.yml&lt;/a&gt; file which will start a full Selenium Grid infrastructure containing the sessions, distributors, router, event bus, and the browsers. You can learn more about the Selenium Grid 4 on their &lt;a href="https://www.selenium.dev/documentation/grid/" rel="noopener noreferrer"&gt;official page&lt;/a&gt; and in their &lt;a href="https://github.com/SeleniumHQ/docker-selenium" rel="noopener noreferrer"&gt;GitHub project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a pre-condition, you need to have Docker installed on your machine and then follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start Docker&lt;/li&gt;
&lt;li&gt;Navigate, through your Command-Line/Terminal app to the project root folder&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;docker-compose up&lt;/code&gt; command&lt;/li&gt;
&lt;li&gt;Access &lt;a href="http://localhost:4444" rel="noopener noreferrer"&gt;http://localhost:4444&lt;/a&gt; to see the Selenium Grid page with the browsers available (Chrome, Edge, and Firefox)&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;general.properties&lt;/code&gt; file, change the &lt;code&gt;target&lt;/code&gt; attribute value to &lt;code&gt;remote&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;code&gt;grid.properties&lt;/code&gt; file in &lt;code&gt;src/main/java/resources&lt;/code&gt; already have the values to connect to a local grid&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Run the &lt;code&gt;BookARoomWebTest&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;you can go to the Selenium Grid dashboard and click on the Sessions tab&lt;/li&gt;
&lt;li&gt;as soon as the test starts a session related to the browser in use will be listed&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  The complete example
&lt;/h1&gt;

&lt;p&gt;You can navigate to the following GitHub repo to see a complete and functional example in the branch &lt;code&gt;local-remote-example&lt;/code&gt;. Spare some time to look at the new classes added and understand how it was structured.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/eliasnogueira/selenium-java-browser-factory/tree/basic-example" rel="noopener noreferrer"&gt;https://github.com/eliasnogueira/selenium-java-browser-factory/tree/basic-example&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>testing</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The best way to add a Request Body to a POST request using Rest-Assured</title>
      <dc:creator>Elias Nogueira </dc:creator>
      <pubDate>Wed, 08 Dec 2021 11:54:10 +0000</pubDate>
      <link>https://dev.to/eliasnogueira/the-best-way-to-add-a-request-body-to-a-post-request-using-rest-assured-3onb</link>
      <guid>https://dev.to/eliasnogueira/the-best-way-to-add-a-request-body-to-a-post-request-using-rest-assured-3onb</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;One of my activities is to review the Quality Engineers’ technical assignment. We ask the candidate to automate at least 2 features in the API and Web layers.&lt;/p&gt;

&lt;p&gt;Most of the candidates are delivering the API test automation solution using Java and Rest-Assured, which is the same combination we use. Of course, we are evaluating it based on the candidate experience in general which includes the whole testing experience, test automation experience, and libraries experience.&lt;/p&gt;

&lt;p&gt;Rest-Assured is a well-known library to use for API test automation, simple to use, and fast. But I can see one gap in most of the solutions they delivered: the lack of knowledge about the library. It’s in different ways and one is unanimous: the use of either &lt;code&gt;String&lt;/code&gt; or &lt;code&gt;HashMap&lt;/code&gt; in the requests.&lt;/p&gt;

&lt;p&gt;The intention here is to tell you which way you can have most of the professional benefits using Rest-Assured as I refer it here as the recommended approach.&lt;/p&gt;

&lt;h1&gt;
  
  
  The test implementation
&lt;/h1&gt;

&lt;p&gt;To not add some complexity here and stay focused on our main goal we will use the &lt;a href="https://reqres.in/" rel="noopener noreferrer"&gt;https://reqres.in/&lt;/a&gt;, a mock API ready to respond to any request for testing purposes.&lt;/p&gt;

&lt;p&gt;As the goal is sent a request with an object with it, sometimes referred to as the payload object, we will use the following endpoint:&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%2Fk21pybvtzvx775kddkta.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%2Fk21pybvtzvx775kddkta.png" alt=" " width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Given the request body, we must send the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;job&lt;/code&gt; attributes, which are text (strings).&lt;/p&gt;

&lt;h1&gt;
  
  
  Working approaches
&lt;/h1&gt;

&lt;h2&gt;
  
  
  String concatenation (not recommended)
&lt;/h2&gt;

&lt;p&gt;The string concatenation approach consists of creating a string with the same output as JSON.&lt;/p&gt;

&lt;p&gt;Note that, on line 5, the &lt;code&gt;String&lt;/code&gt; user is a string concatenation of the JSON Object we must send into the request.&lt;br&gt;
As we are using Java we must escape all the double quotes, as a string starts and ends with it.&lt;br&gt;
The validation on lines 15 and 16 must be hardcoded as well because there is no way to retrieve the data sent because it is a string.&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;class&lt;/span&gt; &lt;span class="nc"&gt;PostTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;postUsingStringConcatenation&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{\"name\":\"Elias\",\"job\":\"Principal Engineer\"}"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;
            &lt;span class="n"&gt;contentType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ContentType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JSON&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;
            &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;
        &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;
            &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/users"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;
        &lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;
            &lt;span class="n"&gt;statusCode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SC_CREATED&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;
            &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Elias"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="s"&gt;"job"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Principal Engineer"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;notNullValue&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                &lt;span class="s"&gt;"createdAt"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;notNullValue&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;p&gt;We can see clearly that this approach works but will give you a lot of maintenance and trouble. You must avoid it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;none&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hard to read&lt;/li&gt;
&lt;li&gt;hard to maintain&lt;/li&gt;
&lt;li&gt;looks unprofessional&lt;/li&gt;
&lt;li&gt;does not allow easy object update (properties or values)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using a HashMap (not recommended, but acceptable)
&lt;/h2&gt;

&lt;p&gt;You can see this approach described in the &lt;a href="https://github.com/rest-assured/rest-assured/wiki/Usage#create-json-from-a-hashmap" rel="noopener noreferrer"&gt;Rest-Assured documentation&lt;/a&gt; but it does not mean this is the best approach.&lt;/p&gt;

&lt;p&gt;This approach consists of creating a &lt;code&gt;HashMap&lt;/code&gt; object to send it on the request.&lt;br&gt;
As a &lt;code&gt;HashMap&lt;/code&gt; as a key-value map where the key is the attribute and value is the attribute value, it seems a good candidate to use.&lt;/p&gt;

&lt;p&gt;On line 5 we are using a &lt;code&gt;Map&lt;/code&gt; typing the attribute as &lt;code&gt;String&lt;/code&gt; and the value as an &lt;code&gt;Object&lt;/code&gt;. This is not the case but you know that a JSON value can be an object.&lt;/p&gt;

&lt;p&gt;On lines 6 and 7 we are adding the key (attribute name) and value (the value we want to send).&lt;/p&gt;

&lt;p&gt;Behind the scene the binding library will transform the &lt;code&gt;HashMap&lt;/code&gt; into a JSON object like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Elias"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"job"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Principal Engineer"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;postUsingHashMap&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user&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;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Elias"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"job"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Principal Engineer"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;
            &lt;span class="n"&gt;contentType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ContentType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JSON&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;
            &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;
        &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;
            &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/users"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;
        &lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;
            &lt;span class="n"&gt;statusCode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SC_CREATED&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;
            &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&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="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;)),&lt;/span&gt;
                &lt;span class="s"&gt;"job"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&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="s"&gt;"job"&lt;/span&gt;&lt;span class="o"&gt;)),&lt;/span&gt;
                &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;notNullValue&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                &lt;span class="s"&gt;"createdAt"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;notNullValue&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;p&gt;This approach is better than the String concatenation and looks more professional, but it’s not the best one…&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give you a clear vision of the attributes and values&lt;/li&gt;
&lt;li&gt;Can enable you to go further and create a class placing the objects, like a test data factory approach&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s not flexible to create complex objects, as you need to create several &lt;code&gt;HashMap&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;An update can cause confusion as you need to set the value in the same key. E.g: &lt;code&gt;put("name", "New value")&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Any typo in the keys will lead to errors that might be hard to find. Eg: &lt;code&gt;put("name", "Elias")&lt;/code&gt; as we have a typo on “o”&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Recommended approach
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Using the Object Mapping
&lt;/h2&gt;

&lt;p&gt;Rest-Assured supports mapping Java objects to and from JSON and XML. This means you can create a Java object and Rest-Assured will try to match all the attributes in the class with either the request or response.&lt;/p&gt;

&lt;p&gt;To be able to use it you need to explicitly add an object mapping library in your classpath. For JSON you need to have either Jackson, Jackson2, Gson, or Johnzon in the classpath and for XML you need JAXB.&lt;/p&gt;

&lt;p&gt;As we are sending information into the request let’s talk about first the Serialization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Object Mapping Serialization
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/rest-assured/rest-assured/wiki/Usage#serialization" rel="noopener noreferrer"&gt;https://github.com/rest-assured/rest-assured/wiki/Usage#serialization&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rest-Assured will use one of the object mapping libraries you added into your classpath to bind the attributes from a Java object into the request body. We already know that we required, for this example, the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;job&lt;/code&gt; attributes to post an user. The Java object will look like this:&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;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;User&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;name&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;job&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&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;setName&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;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

      &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getJob&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&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;setJob&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;job&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;job&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;p&gt;In the test, we need first to create the &lt;code&gt;User&lt;/code&gt; object with the data we would like to use. You can see this on line 6.&lt;/p&gt;

&lt;p&gt;Now we simply use the &lt;code&gt;user&lt;/code&gt; object into the body(object). It’s important to explicitly set the Content-type. You can see it in lines 9 and 10.&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;class&lt;/span&gt; &lt;span class="nc"&gt;PostTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;postUsingObjectMapping&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&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;User&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Elias"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Principal Engineer"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;
            &lt;span class="n"&gt;contentType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ContentType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JSON&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;
            &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;
        &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;
            &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/users"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;
        &lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;
            &lt;span class="n"&gt;statusCode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SC_CREATED&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;
            &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getNama&lt;/span&gt;&lt;span class="o"&gt;()),&lt;/span&gt;
                &lt;span class="s"&gt;"job"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getJob&lt;/span&gt;&lt;span class="o"&gt;()),&lt;/span&gt;
                &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;notNullValue&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                &lt;span class="s"&gt;"createdAt"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;notNullValue&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;p&gt;Rest-Assured will do the magic when the &lt;code&gt;body()&lt;/code&gt; method uses an object where it will try to find the required request attribute names into the object used.&lt;/p&gt;

&lt;p&gt;The request needs the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;job&lt;/code&gt; attributes, as text. As the &lt;code&gt;User&lt;/code&gt; object has the &lt;code&gt;name&lt;/code&gt; and job attributes as String (text) RestAssured will to the automatic value match. Both combinations of attribute and value match are called Object Serialization.&lt;/p&gt;

&lt;h1&gt;
  
  
  Important note
&lt;/h1&gt;

&lt;p&gt;You might face the following exception, which is super self-explanatory:&lt;/p&gt;

&lt;p&gt;java.lang.IllegalStateException: Cannot serialize object because no JSON serializer found in the classpath. Please put Jackson (Databind), Gson, Johnzon, or Yasson in the classpath.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:72)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:59)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:263)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:277)
at io.restassured.internal.mapping.ObjectMapping.serialize(ObjectMapping.groovy:160)
at io.restassured.internal.mapping.ObjectMapping$serialize.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at io.restassured.internal.RequestSpecificationImpl.body(RequestSpecificationImpl.groovy:751)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will happen if you don’t add any library to serialize the objects. You need to explicitly add one of the following libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind" rel="noopener noreferrer"&gt;Jackson (databind)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mvnrepository.com/artifact/com.google.code.gson/gson" rel="noopener noreferrer"&gt;Gson&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mvnrepository.com/artifact/org.apache.johnzon/johnzon-core" rel="noopener noreferrer"&gt;Johnzon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It might be the case you are not using one of these libraries, having a successful test execution. Some dependencies can have one of these as an internal dependency, and you can figure out it simply by running &lt;code&gt;mvn dependency:tree&lt;/code&gt; and trying to look at one of the libraries mentioned.&lt;/p&gt;

&lt;h1&gt;
  
  
  Examples
&lt;/h1&gt;

&lt;p&gt;In the &lt;a href="https://github.com/eliasnogueira/restassured-complete-basic-example" rel="noopener noreferrer"&gt;restassured-complete-basic-example&lt;/a&gt; project, you can find the &lt;a href="https://github.com/eliasnogueira/restassured-complete-basic-example/tree/master/src/main/java/com/eliasnogueira/credit/model" rel="noopener noreferrer"&gt;Simulation&lt;/a&gt; model, which models the request and response for the Simulations API.&lt;/p&gt;

&lt;p&gt;The model is in use by the &lt;a href="https://github.com/eliasnogueira/restassured-complete-basic-example/blob/master/src/main/java/com/eliasnogueira/credit/data/factory/SimulationDataFactory.java" rel="noopener noreferrer"&gt;SimulaitonDataFactory&lt;/a&gt; to create the &lt;code&gt;Simulation&lt;/code&gt; data, necessary to make the &lt;code&gt;POST&lt;/code&gt; request using the body parameter.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/eliasnogueira/restassured-complete-basic-example/blob/master/src/test/java/com/eliasnogueira/credit/simulations/SimulationsFunctionalTest.java" rel="noopener noreferrer"&gt;SimulationFunctionalTest&lt;/a&gt; has tests using different HTTP methods. You can see the &lt;a href="https://github.com/eliasnogueira/restassured-complete-basic-example/blob/3cf33c71b80a8508cae47eb7bf63e933d62c1567/src/test/java/com/eliasnogueira/credit/simulations/SimulationsFunctionalTest.java#L130-L147" rel="noopener noreferrer"&gt;createNewSimulationSuccessfully&lt;/a&gt;, &lt;a href="https://github.com/eliasnogueira/restassured-complete-basic-example/blob/3cf33c71b80a8508cae47eb7bf63e933d62c1567/src/test/java/com/eliasnogueira/credit/simulations/SimulationsFunctionalTest.java#L149-L162" rel="noopener noreferrer"&gt;invalidSimulations&lt;/a&gt;, and &lt;a href="https://github.com/eliasnogueira/restassured-complete-basic-example/blob/3cf33c71b80a8508cae47eb7bf63e933d62c1567/src/test/java/com/eliasnogueira/credit/simulations/SimulationsFunctionalTest.java#L164-L177" rel="noopener noreferrer"&gt;simulationWithDuplicatedCpf&lt;/a&gt; test methods using the &lt;code&gt;Simulation&lt;/code&gt; object to &lt;code&gt;POST&lt;/code&gt; a body using it instead of &lt;code&gt;Strings&lt;/code&gt; or any other mentioned approach.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Reasons to avoid RandomStringUtils for test data generation</title>
      <dc:creator>Elias Nogueira </dc:creator>
      <pubDate>Fri, 15 Oct 2021 15:24:24 +0000</pubDate>
      <link>https://dev.to/eliasnogueira/reasons-to-avoid-randomstringutils-for-test-data-generation-ope</link>
      <guid>https://dev.to/eliasnogueira/reasons-to-avoid-randomstringutils-for-test-data-generation-ope</guid>
      <description>&lt;h2&gt;
  
  
  Which problem do we want to solve?
&lt;/h2&gt;

&lt;p&gt;We will try to solve one of the worst practices used on tests at any level: fixed/hard-coded data.&lt;/p&gt;

&lt;p&gt;I want to avoid as much as possible any manual pre-action before I can run my tests and, because of that, I try to avoid as well the usage of static files (CSV, TXT, XLS, JSON).&lt;/p&gt;

&lt;p&gt;Here we will see a common usage from Java developers: the &lt;code&gt;RamdomStringUItils&lt;/code&gt; and how it might not be the best choice for automatic data generation.&lt;/p&gt;

&lt;p&gt;By the way, I recommend the automatic data generation in the tests using the Test Data Factory approach, and you can find an example here in my blog: &lt;a href="http://www.eliasnogueira.com/test-data-factory-why-and-how-to-use" rel="noopener noreferrer"&gt;Test Data Factory: Why and How to Use&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The examples described here are simple, without the usage of the Test Data Factory, and will show you why the &lt;code&gt;RandomStringUtils&lt;/code&gt; might not be the best approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;We will automatically generate data to a Customer object with has the following criteria:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Constraints&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;Not null&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Not null and size between 2 and 50 characters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;profession&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Not null and size between 2 and 30 characters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;accountNumber&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Not null and size as 18 characters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;address&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Not null and size between 2 and 50 characters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;phoneNumber&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Not null and size between 11 and 14 characters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;birthday&lt;/td&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;Not null&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To reduce the number of tests, the key point is to generate valid data given the constraints. In a professional environment, we would implement the tests for the edge cases as well.&lt;/p&gt;

&lt;p&gt;Think about this Customer data as an object used in any test level (unit, integration, service, UI).&lt;/p&gt;

&lt;h2&gt;
  
  
  What does the RandomStringUtils class do?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://commons.apache.org/proper/commons-lang/javadocs/api-release/index.html" rel="noopener noreferrer"&gt;RandomStringUtils&lt;/a&gt; is a class from the &lt;a href="https://commons.apache.org/proper/commons-lang/" rel="noopener noreferrer"&gt;Apache Commons Lang&lt;/a&gt; library that generates random Strings based on different conditions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;length&lt;/li&gt;
&lt;li&gt;letters&lt;/li&gt;
&lt;li&gt;numbers&lt;/li&gt;
&lt;li&gt;alphanumeric&lt;/li&gt;
&lt;li&gt;ASCII&lt;/li&gt;
&lt;li&gt;numeric&lt;/li&gt;
&lt;li&gt;print&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s a static class where you can directly generate any String, so it’s super handy!&lt;/p&gt;

&lt;p&gt;See the example below, where you can generate a different set of random data.&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;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RandomStringUtilsExample&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;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// returns a String with 5 numbers&lt;/span&gt;
        &lt;span class="c1"&gt;// example 82114&lt;/span&gt;
        &lt;span class="nc"&gt;RandomStringUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomNumeric&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// returns an alphanumeric String with length as 30 mixing upper and lower cases&lt;/span&gt;
        &lt;span class="c1"&gt;// example gQ6RB8MiwKOg9O3qnHFo7I3jilHoIy&lt;/span&gt;
        &lt;span class="nc"&gt;RandomStringUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomAlphanumeric&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&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;h3&gt;
  
  
  What is the result of using RandomStringUtils class?
&lt;/h3&gt;

&lt;p&gt;Let’s first take a look at the code example implementing the usage of &lt;code&gt;RamdonStringUtils&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;in line 7 is using the &lt;code&gt;RandomStringUtils.randomNumeric()&lt;/code&gt; method to generate an &lt;code&gt;int&lt;/code&gt; value and, to make it, possible we are parsing the &lt;code&gt;String&lt;/code&gt; into Int using &lt;code&gt;Integer.valueOf()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the lines 8 to 12 uses &lt;code&gt;RandomStringUtils.randomAlphanumeric()&lt;/code&gt; to generate alphanumeric data&lt;/li&gt;
&lt;li&gt;line 13 has a fixed date as now (today) because &lt;code&gt;RandomStringUtils&lt;/code&gt; generates only &lt;code&gt;Strings&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BasicExampleTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data validations using RandomStringUtils"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;randomStringUtils&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;CustomerData&lt;/span&gt; &lt;span class="n"&gt;customerData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CustomerData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;
                &lt;span class="n"&gt;id&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;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RandomStringUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomNumeric&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;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RandomStringUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomNumeric&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;
                &lt;span class="n"&gt;profession&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RandomStringUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomAlphanumeric&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;
                &lt;span class="n"&gt;accountNumber&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RandomStringUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomAlphanumeric&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;
                &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RandomStringUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomAlphanumeric&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;
                &lt;span class="n"&gt;phoneNumber&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RandomStringUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomAlphanumeric&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;
                &lt;span class="n"&gt;birthday&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;Date&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;
                &lt;span class="n"&gt;build&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;p&gt;The output of the test execution, if we print or inspect the &lt;code&gt;customerData&lt;/code&gt; object, is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1335130963&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GGXS19kN6kSuzHwW6T0YjJCxUaIyKKmAaUdQH51gdUAtt1TwqY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"profession"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0kk8HSiFgCUVfLzbD3PyR6cn8j0LH3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"accountNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PqvekXb9ekRAJi3ypy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"90lqP2LHnQMWtmMP8vasO3BR5dsICIL85u5sJ0yjGKWXxCkFsj"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"phoneNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"OpoJ3tOE53woy9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"birthday"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sep 26, 2021, 10:01:10 PM"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could successfully generate the necessary data! Yay!&lt;/p&gt;

&lt;h2&gt;
  
  
  What does JavaFaker do?
&lt;/h2&gt;

&lt;p&gt;[]JavaFaker](&lt;a href="https://github.com/DiUS/java-faker" rel="noopener noreferrer"&gt;https://github.com/DiUS/java-faker&lt;/a&gt;) is an open-source library based on &lt;a href="https://github.com/stympy/faker" rel="noopener noreferrer"&gt;Faker&lt;/a&gt; to generate fake data.&lt;/p&gt;

&lt;p&gt;There’ are some nonsense data generation there like Avatar, Friends, etc.., but there’s also a good set of objects that can generate data in certain conditions that matches our necessities.&lt;/p&gt;

&lt;p&gt;I invite you to take a look at the GitHub repo and see the different objects to generate data.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the result of using JavaFaker?
&lt;/h3&gt;

&lt;p&gt;The code implementation to generate data using the &lt;code&gt;CustomerData&lt;/code&gt; class is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;in line 9, the &lt;code&gt;number()&lt;/code&gt; method is in use to generate a random number&lt;/li&gt;
&lt;li&gt;in line 10, the &lt;code&gt;name()&lt;/code&gt; method is in use to generate a full name&lt;/li&gt;
&lt;li&gt;in line 11, the &lt;code&gt;company()&lt;/code&gt; is in use to generate a profession&lt;/li&gt;
&lt;li&gt;in line 12, the &lt;code&gt;finance()&lt;/code&gt; method is in use to generate a valid IBAN for the Netherlands country&lt;/li&gt;
&lt;li&gt;in line 13, the &lt;code&gt;address()&lt;/code&gt; method is in use to generate a full street address&lt;/li&gt;
&lt;li&gt;in line 14, the p&lt;code&gt;honeNumber()&lt;/code&gt; method is in use to generate a cell phone number&lt;/li&gt;
&lt;li&gt;in line 15, the &lt;code&gt;date()&lt;/code&gt; method is in use to generate birthday data with the age between 18 and 90
&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BasicExampleTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data validations using faker library"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Faker&lt;/span&gt; &lt;span class="n"&gt;faker&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;Faker&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;CustomerData&lt;/span&gt; &lt;span class="n"&gt;customerData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CustomerData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;
                &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;randomNumber&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;
                &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;
                &lt;span class="n"&gt;profession&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;company&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;profession&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;
                &lt;span class="n"&gt;accountNumber&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;finance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;iban&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NL"&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;
                &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;streetAddress&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;
                &lt;span class="n"&gt;phoneNumber&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;phoneNumber&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;cellPhone&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;
                &lt;span class="n"&gt;birthday&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;birthday&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;
                &lt;span class="n"&gt;build&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;p&gt;The output of the test execution, if we print or inspect the &lt;code&gt;customerData&lt;/code&gt; object, is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;520543&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tena Pagac"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"profession"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"photographer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"accountNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NL07HUUN1518167413"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12672 Romaguera Tunnel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"phoneNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(561) 638-5813"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"birthday"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mar 5, 1982, 10:29:18 AM"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could successfully generate the necessary data! But let’s not focus on the differences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing both approaches
&lt;/h2&gt;

&lt;p&gt;There’re two aspects I would like to consider to choose between one approach or another:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;legibility of future troubleshooting (log analysis)&lt;/li&gt;
&lt;li&gt;easy data creation in different criteria&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can see the main differences comparing the data result side by side (click on the image to expand it):&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%2Fs66elgd4549594pzgub5.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%2Fs66elgd4549594pzgub5.png" alt=" " width="800" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Legibility of future troubleshooting (analysis)
&lt;/h3&gt;

&lt;p&gt;The regular activity for an engineer that writes code is troubleshooting: we constantly see the logs and debug the application to understand current and future problems in the code.&lt;/p&gt;

&lt;p&gt;Now imagine yourself looking at the CustomerData object where the data was filled in with the RandomStringUtils approach: it’s hard to correlate the data you have with a list of objects you might get or even taking a look at the data used inside a log file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Easy data creation in different criteria
&lt;/h3&gt;

&lt;p&gt;For most of the attributes present in the &lt;code&gt;CustomerData&lt;/code&gt; class, you can use &lt;code&gt;RandomStringUtils&lt;/code&gt; to generate the different criteria. For example, you can easily set 51 characters to the name attribute and expect a failing constraint validation using &lt;code&gt;RandomStringUtils.randomAlphanumeric(51);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For more specialized data, like phone number and date you need a proper library, and JavaFaker can generate both data.&lt;/p&gt;

&lt;p&gt;In this way, we can make the process easier by adopting one library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerations
&lt;/h2&gt;

&lt;p&gt;Of course, I’m put more emphasis on the JavaFaker library because we have almost everything we need to generate data, but it does not exclude a possible necessity to use the RandomStringUtils class or any other class placed in the Apache Commons library.&lt;/p&gt;

&lt;p&gt;The main consideration here is the ability to generate all the possible data you need using a single source of truth without reinventing the wheel, as well as the indirect benefits it will show during the troubleshooting process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/eliasnogueira/avoid-random-string-utils" rel="noopener noreferrer"&gt;avoid-random-string-utils&lt;/a&gt; project shows a basic example comparing RandomStringUtils vs JavaFaker.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/eliasnogueira/restassured-complete-basic-example" rel="noopener noreferrer"&gt;restassured-complete-basic-example&lt;/a&gt; project has a &lt;a href="https://github.com/eliasnogueira/restassured-complete-basic-example/blob/master/src/main/java/com/eliasnogueira/credit/data/factory/SimulationDataFactory.java" rel="noopener noreferrer"&gt;factory data&lt;/a&gt; class to generate all the necessary data in different conditions. It’s a good real-world example.&lt;/p&gt;

</description>
      <category>java</category>
      <category>testing</category>
      <category>testdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Thoughts on Selenium 101 Certification from LambdaTest</title>
      <dc:creator>Elias Nogueira </dc:creator>
      <pubDate>Tue, 23 Mar 2021 21:37:15 +0000</pubDate>
      <link>https://dev.to/eliasnogueira/thoughts-on-selenium-101-certification-from-lambdatest-kbi</link>
      <guid>https://dev.to/eliasnogueira/thoughts-on-selenium-101-certification-from-lambdatest-kbi</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.lambdatest.com/" rel="noopener noreferrer"&gt;LambdaTest&lt;/a&gt; created their different &lt;a href="https://www.lambdatest.com/certifications/" rel="noopener noreferrer"&gt;Certifications&lt;/a&gt; delivering them at free cost! They have a &lt;a href="https://www.lambdatest.com/blog/lambdatest-certifications-learning-hub/" rel="noopener noreferrer"&gt;detailed announcement&lt;/a&gt; on their blog.&lt;/p&gt;

&lt;p&gt;I took the Selenium 101 exam and I passed. I will share my thought with you.&lt;/p&gt;

&lt;h2&gt;
  
  
  My thoughts
&lt;/h2&gt;

&lt;p&gt;First of all, I don’t believe that much about certifications that don’t have a way to make you practice it.&lt;/p&gt;

&lt;p&gt;I do recommend for everyone who wants to take testing/quality paid certifications like ISTQB or related the following: invest your time and money into courses, books, and practicing the tech skills most of the open positions in the market required. It will worth your time, money, and dedication.&lt;/p&gt;

&lt;p&gt;I’m not telling you to give up your current focus on those certifications if you have. I truly believe you will learn something valuable. My main concern is regarding the experience you can have from different sources and get prepared for your dream job.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about the LambdaTest certification?
&lt;/h3&gt;

&lt;p&gt;I would say it worth your time. I liked it because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;there are multiple-choice questions&lt;/li&gt;
&lt;li&gt;there is an assignment task&lt;/li&gt;
&lt;li&gt;it’s free!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Part 1: Multiple choice questions
&lt;/h3&gt;

&lt;p&gt;You need to select the correct questions regarding a topic. The same procedure that all certification has. There are some questions I think don’t belong/fit into the Selenium knowledge base like questions about Apache POI and Excel files, regexp, and Selenium 1.&lt;/p&gt;

&lt;p&gt;I might consider the Selenium 1 questions valid for those that have legacy code wrote down in these versions, but I would say it’s unusual.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 2: Assignment task
&lt;/h3&gt;

&lt;p&gt;I loved this one. They will give you a web app link and the e2e scenario to automate. A real e2e scenario.&lt;/p&gt;

&lt;p&gt;There’s only one thing I think is not that valid to reproduce, which is a download part, but you might see a weird requirement from your PO to test if the PDF report can be download (!!!).&lt;/p&gt;

&lt;p&gt;You must deliver the assignment task in a “short” period, so get prepared.&lt;br&gt;
Btw, it should be functional and run because they will do it!&lt;/p&gt;

&lt;p&gt;I would say to deliver the assignment in a functional way rather than the most beautiful code you can create with some design patterns. The focus is to show that you know how to automate an e2e scenario.&lt;/p&gt;

&lt;h3&gt;
  
  
  Are you ready?
&lt;/h3&gt;

&lt;p&gt;Are you ready to give it a try? If you are an experienced engineer you can “play” with the assignment and even learn something new. If you are learning Selenium this is a good way to validate your knowledge.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>certification</category>
      <category>java</category>
      <category>career</category>
    </item>
    <item>
      <title>100 Best Tips about Java Testing tools</title>
      <dc:creator>Elias Nogueira </dc:creator>
      <pubDate>Sun, 07 Feb 2021 13:25:02 +0000</pubDate>
      <link>https://dev.to/eliasnogueira/100-best-tips-about-java-and-testing-46c4</link>
      <guid>https://dev.to/eliasnogueira/100-best-tips-about-java-and-testing-46c4</guid>
      <description>&lt;p&gt;I started a new initiative 100 days ago: post daily tips about Testing tools you can use with Java!&lt;/p&gt;

&lt;p&gt;I posted it on Twitter and LinkedIn.&lt;br&gt;
By the way, don’t hesitate to follow/add me!&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the tools?
&lt;/h2&gt;

&lt;p&gt;I have covered the following tools that can give you complete test coverage and deliver bug-free high-quality software.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://junit.org/junit5/" rel="noopener noreferrer"&gt;JUnit5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiremock.org/" rel="noopener noreferrer"&gt;WireMock&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rest-assured.io/" rel="noopener noreferrer"&gt;RestAssured&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.selenium.dev/" rel="noopener noreferrer"&gt;Selenium WebDriver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://testng.org/doc/" rel="noopener noreferrer"&gt;TestNG&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where the tips based?
&lt;/h2&gt;

&lt;p&gt;Believe me or not: from the official tool documentation!&lt;br&gt;
I’ve learned a lot from the official documentation. I always start from there.&lt;/p&gt;

&lt;p&gt;Each tip has a link for the feature documentation. Don’t forget to click on it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Where can I find the tips?
&lt;/h2&gt;

&lt;p&gt;I’ve created a simple webpage where you can see all the tips or filter them by one of the tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eliasnogueira.github.io/100-tips-testing-java" rel="noopener noreferrer"&gt;https://eliasnogueira.github.io/100-tips-testing-java&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would you like to see how I created the web page? (please don’t judge me, I’m not a frontend engineer 😛 ). You can access the following GitHub repo &lt;a href="[https://github.com/eliasnogueira/100-tips-testing-java"&gt;https://github.com/eliasnogueira/100-tips-testing-java&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>java</category>
      <category>100daysofcode</category>
    </item>
  </channel>
</rss>
