<?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: Edward</title>
    <description>The latest articles on DEV Community by Edward (@edwardmrdoian).</description>
    <link>https://dev.to/edwardmrdoian</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4225039%2F77a56cfa-6215-43cc-8324-5f9e37afff49.jpg</url>
      <title>DEV Community: Edward</title>
      <link>https://dev.to/edwardmrdoian</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/edwardmrdoian"/>
    <language>en</language>
    <item>
      <title>How I structure a Java test automation project (and the free template I made from it)</title>
      <dc:creator>Edward</dc:creator>
      <pubDate>Tue, 03 Nov 2026 22:14:29 +0000</pubDate>
      <link>https://dev.to/edwardmrdoian/how-i-structure-a-java-test-automation-project-and-the-free-template-i-made-from-it-49il</link>
      <guid>https://dev.to/edwardmrdoian/how-i-structure-a-java-test-automation-project-and-the-free-template-i-made-from-it-49il</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Keep assertions only in tests. Give every parallel test its own browser. Mock APIs for logic checks. Tag tests as smoke or regression. I turned all of this into a free GitHub template you can clone today.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every time I started a new test automation project, the first weeks went to the same chores: choosing library versions, deciding on folders, wiring reports, writing a pipeline.&lt;/p&gt;

&lt;p&gt;After the fifth time, I turned my setup into a template. This post explains the structure and the rules behind it, so you can use them even if you never clone the repo.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧭 The one rule that keeps projects clean
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tests assert. Everything else acts.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Assertions?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Page objects&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Click and type&lt;/td&gt;
&lt;td&gt;Never&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API clients&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Send requests and return the response&lt;/td&gt;
&lt;td&gt;Never&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Repositories&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Run SQL&lt;/td&gt;
&lt;td&gt;Never&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Check the result&lt;/td&gt;
&lt;td&gt;Always&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Because only tests contain assertions, you can reuse every page, client and query in any test without surprises. Here is a page object from the template:&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;LoginPage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BasePage&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Step&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Login as {username}"&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;LoginPage&lt;/span&gt; &lt;span class="nf"&gt;loginAs&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;username&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;locator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#username"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;locator&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;fill&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;locator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"button[type='submit']"&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="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;String&lt;/span&gt; &lt;span class="nf"&gt;flashMessage&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;locator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#flash"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;innerText&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;And the test that uses 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="nd"&gt;@Test&lt;/span&gt;
&lt;span class="nd"&gt;@Tag&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"smoke"&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;validLogin&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;LoginPage&lt;/span&gt; &lt;span class="n"&gt;page&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;LoginPage&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;open&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;loginAs&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tomsmith"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"SuperSecretPassword!"&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;page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flashMessage&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"You logged into a secure area!"&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;page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentUrl&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;endsWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/secure"&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;There is no sleep and no wait code. Playwright waits for each element to be ready before it acts.&lt;/p&gt;


&lt;h2&gt;
  
  
  ⚡ Parallel runs without flaky chaos
&lt;/h2&gt;

&lt;p&gt;Fast suites run tests in parallel, and that breaks anything that shares a browser.&lt;/p&gt;

&lt;p&gt;The template gives &lt;strong&gt;every test its own isolated browser session&lt;/strong&gt;. A small manager stores one session per thread, and a JUnit extension starts and closes it around each test. When a test fails, the same extension attaches a screenshot and a Playwright trace to the report.&lt;/p&gt;

&lt;p&gt;The trace is the feature I would not give up. You replay the failed run step by step, with page snapshots and network calls, instead of guessing from a stack trace.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧪 Mock-first API tests
&lt;/h2&gt;

&lt;p&gt;Tests against a public test API fail when that API is slow or down. For logic checks I stub the service with WireMock and keep only a few tests against the real 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="n"&gt;wm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stubFor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urlEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/users/2"&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="na"&gt;willReturn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;okJson&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matchesJsonSchemaInClasspath&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"schemas/user-response.json"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The JSON schema check turns the response into a contract, so a renamed field fails the test even if the status code is still 200.&lt;/p&gt;


&lt;h2&gt;
  
  
  🔎 Queues and log search without hand-written JSON
&lt;/h2&gt;

&lt;p&gt;If your system uses RabbitMQ or Elasticsearch, tests need small helpers or they turn into copy-pasted boilerplate. A fluent query builder keeps Elasticsearch requests readable:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ElasticQueryBuilder&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ElasticQueryBuilder&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="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filterTerm&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"service.keyword"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"payments"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filterRange&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"@timestamp"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"now-1h"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sortBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"@timestamp"&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="na"&gt;size&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="nc"&gt;SearchResult&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;elastic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;waitForHits&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&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="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The waiting method polls, because Elasticsearch needs about a second before a new document becomes searchable. That is a place where a fixed sleep always ends up wrong.&lt;/p&gt;


&lt;h2&gt;
  
  
  🏷️ Smoke and regression with tags
&lt;/h2&gt;

&lt;p&gt;Every test carries a &lt;strong&gt;layer tag&lt;/strong&gt; (&lt;code&gt;ui&lt;/code&gt;, &lt;code&gt;api&lt;/code&gt;, &lt;code&gt;db&lt;/code&gt;, &lt;code&gt;integration&lt;/code&gt;) and a &lt;strong&gt;level tag&lt;/strong&gt; (&lt;code&gt;smoke&lt;/code&gt; or &lt;code&gt;regression&lt;/code&gt;). Pull requests run only smoke, and the nightly run does everything:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mvn clean &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-Dgroups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;smoke
mvn clean &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-Dgroups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"api &amp;amp; regression"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Failed tests retry once with &lt;code&gt;-Drerun.count=1&lt;/code&gt;, and the report marks them as flaky, so retries never hide a problem.&lt;/p&gt;


&lt;h2&gt;
  
  
  🚀 Try the template
&lt;/h2&gt;

&lt;p&gt;The whole structure is available as a free GitHub template with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Playwright&lt;/strong&gt; UI tests with screenshots and traces on failure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REST Assured + WireMock&lt;/strong&gt; for API tests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database, RabbitMQ and Elasticsearch&lt;/strong&gt; helpers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Allure&lt;/strong&gt; reports and a &lt;strong&gt;GitHub Actions&lt;/strong&gt; pipeline&lt;/li&gt;
&lt;li&gt;Secrets read from environment variables&lt;/li&gt;
&lt;li&gt;A script that renames everything to your own package
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/edwardmrdoian/qa-enterprise-template
./scripts/new-project.sh com.acme.qa acme-qa-tests
mvn clean &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-Dgroups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;smoke
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/edwardmrdoian" rel="noopener noreferrer"&gt;
        edwardmrdoian
      &lt;/a&gt; / &lt;a href="https://github.com/edwardmrdoian/qa-enterprise-template" rel="noopener noreferrer"&gt;
        qa-enterprise-template
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Production-ready QA automation template in Java: Playwright UI, REST Assured + WireMock API, JDBI database, RabbitMQ and Elasticsearch/ELK helpers. JUnit 5 parallel runs, Allure reports with failure traces, GitHub Actions CI. Clone, rename with one script, and start writing tests.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;QA Enterprise Template&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;A Java &lt;strong&gt;25&lt;/strong&gt; starter for maintainable UI, API, database, RabbitMQ and Elasticsearch tests
The default suite checks the framework using &lt;strong&gt;real local infrastructure or isolated mocks&lt;/strong&gt;
Chromium against a local HTTP fixture, REST Assured against WireMock, and JDBI against H2.
Public demo services and Docker-backed examples are explicitly opt-in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stack:&lt;/strong&gt; Maven Wrapper 3.9.9, JUnit 5, Playwright, REST Assured, WireMock, AssertJ,
Awaitility, Jackson, JDBI/HikariCP, Owner, Datafaker/Instancio, Allure and Spotless.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;1. Create your project&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Install &lt;strong&gt;JDK 25&lt;/strong&gt; and set &lt;code&gt;JAVA_HOME&lt;/code&gt;; no global Maven installation is needed.
Use GitHub's &lt;strong&gt;Use this template&lt;/strong&gt; button when enabled, or clone into a new repository.
Keep the MIT license notice when redistributing template code.&lt;/p&gt;
&lt;p&gt;From the project root, initialize the Java package, Maven coordinates and display name:&lt;/p&gt;
&lt;div class="highlight highlight-source-powershell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Windows (also works in PowerShell on Linux/macOS)&lt;/span&gt;
.&lt;span class="pl-c1"&gt;\scripts\new-project.ps1&lt;/span&gt; com.acme.qa acme&lt;span class="pl-k"&gt;-&lt;/span&gt;qa&lt;span class="pl-k"&gt;-&lt;/span&gt;tests &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Acme QA Tests&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Linux/macOS or Git&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/edwardmrdoian/qa-enterprise-template" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;If it saves you time, a ⭐ on GitHub helps other testers find it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What would you add to a template like this? Tell me in the comments.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>java</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
