<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Manjunath HK</title>
    <description>The latest articles on Forem by Manjunath HK (@manjunath_hk_b1c69fbb115e).</description>
    <link>https://forem.com/manjunath_hk_b1c69fbb115e</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%2F3812700%2F959505a3-cd50-483c-9bc7-94d18d3feffe.png</url>
      <title>Forem: Manjunath HK</title>
      <link>https://forem.com/manjunath_hk_b1c69fbb115e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/manjunath_hk_b1c69fbb115e"/>
    <language>en</language>
    <item>
      <title>SDETs &amp; QA Engineers: We Need to Talk About Your Git</title>
      <dc:creator>Manjunath HK</dc:creator>
      <pubDate>Sun, 08 Mar 2026 09:38:16 +0000</pubDate>
      <link>https://forem.com/manjunath_hk_b1c69fbb115e/sdets-qa-engineers-we-need-to-talk-about-your-git-2npd</link>
      <guid>https://forem.com/manjunath_hk_b1c69fbb115e/sdets-qa-engineers-we-need-to-talk-about-your-git-2npd</guid>
      <description>&lt;p&gt;I've reviewed a lot of test repositories over the years.&lt;/p&gt;

&lt;p&gt;Some of them were clean, well-structured, and a pleasure to navigate. Most of them looked like someone had committed code at 11pm with the keyboard slightly on fire.&lt;/p&gt;

&lt;p&gt;Vague commits. Branches that had been "open since Q2." Pull requests with descriptions that just said &lt;em&gt;"added tests."&lt;/em&gt; Merge conflicts so deep they required archaeological excavation. And — the classic — a direct push to &lt;code&gt;main&lt;/code&gt; with the message &lt;code&gt;wip&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's the uncomfortable truth: &lt;strong&gt;the people responsible for software quality are often running some of the least disciplined codebases in the organization.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This isn't a skill problem. It's a culture and priority problem. And it's time we address it directly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Happens (And Why It's Not Entirely Your Fault)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Test code gets treated as second-class code
&lt;/h3&gt;

&lt;p&gt;In a lot of orgs, there's an implicit hierarchy: production code matters, test code is just scaffolding. Nobody reviews it rigorously. No one asks about its internal quality. As long as the tests run and the pipeline is green, it's invisible.&lt;/p&gt;

&lt;p&gt;That invisibility creates permission. And permission creates drift.&lt;/p&gt;

&lt;h3&gt;
  
  
  The urgency trap
&lt;/h3&gt;

&lt;p&gt;QA is the last gate before a release. When a release is in two hours and a test needs to be fixed, nobody is creating a well-named branch, writing a conventional commit, and opening a PR with a template. They're pushing directly to main and hoping nobody notices.&lt;/p&gt;

&lt;p&gt;The problem: &lt;em&gt;someone always notices eventually&lt;/em&gt; — usually when a three-month-old direct push causes a regression at 2am.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nobody taught us this formally
&lt;/h3&gt;

&lt;p&gt;A lot of SDETs transitioned from manual QA or came up through non-engineering paths. You learned enough Git to clone, commit, and push. But trunk-based development, branch strategies, &lt;code&gt;git rebase&lt;/code&gt;, conventional commits — those were never in the onboarding plan.&lt;/p&gt;

&lt;p&gt;This isn't a failure of individuals. It's a failure of how the industry onboards QA talent.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Bad Git Discipline Actually Costs You
&lt;/h2&gt;

&lt;p&gt;This isn't just about aesthetics or "best practices" energy. The consequences are real:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔴 &lt;strong&gt;Broken nightly runs&lt;/strong&gt; — one sloppy merge to &lt;code&gt;main&lt;/code&gt; breaks the entire regression suite overnight&lt;/li&gt;
&lt;li&gt;🕵️ &lt;strong&gt;Untraceable flaky tests&lt;/strong&gt; — when your commit history is noise, isolating &lt;em&gt;when&lt;/em&gt; something broke becomes a multi-hour investigation&lt;/li&gt;
&lt;li&gt;🧱 &lt;strong&gt;Merge conflict purgatory&lt;/strong&gt; — a branch that's been open for 3 weeks diverges so hard it becomes a full-day rebase session&lt;/li&gt;
&lt;li&gt;🤝 &lt;strong&gt;Loss of developer trust&lt;/strong&gt; — devs stop trusting the test pipeline when they can't reason about what changed and when&lt;/li&gt;
&lt;li&gt;😰 &lt;strong&gt;Painful onboarding&lt;/strong&gt; — new SDETs joining your team spend days just trying to understand the repo state instead of writing tests&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Anti-Patterns (Raise Your Hand If You've Done One)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🚩 The Mega-Commit
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit -m "stuff"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Changed files: 14. Includes: 3 new test files, 2 refactored page objects, an updated config, and a commented-out block from 2021 nobody wants to delete.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Impossible to review. Impossible to revert cleanly. Communicates nothing.&lt;/p&gt;




&lt;h3&gt;
  
  
  🚩 The WIP Push to Main
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Message: &lt;code&gt;wip&lt;/code&gt; / &lt;code&gt;testing&lt;/code&gt; / &lt;code&gt;fix&lt;/code&gt; / &lt;code&gt;asdf&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Even in a solo project, this destroys your ability to understand your own history. In a team context, it's a live grenade.&lt;/p&gt;




&lt;h3&gt;
  
  
  🚩 The Immortal Branch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat/big-test-refactor  (last commit: 6 weeks ago)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nobody's sure if it's still active. It's diverged by 200 commits. The person who created it has since moved to a different squad. Nobody wants to touch it. It just... lives there.&lt;/p&gt;




&lt;h3&gt;
  
  
  🚩 The Copy-Paste PR
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;PR Title: "Tests"&lt;br&gt;
Description: "Added some tests for the checkout flow."&lt;br&gt;
Linked ticket: &lt;em&gt;(none)&lt;/em&gt;&lt;br&gt;
CI status: 🔴&lt;br&gt;
Reviews: 0&lt;br&gt;
Status: &lt;strong&gt;Merged&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🚩 The Ignored Red Build
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;"Oh the pipeline's been red for a week, it's just a flaky test. I'll merge anyway."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once you normalize merging on red, the signal disappears entirely. Your CI becomes decoration.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Industry-Standard Lifecycle (For Test Code Specifically)
&lt;/h2&gt;

&lt;p&gt;Here's what disciplined version control looks like in the SDET context — not for production code, &lt;em&gt;for your test repos.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — Branch with intention
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Branch from develop (or main, per your team's model)&lt;/span&gt;
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;/JIRA-512-checkout-e2e-validation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Naming convention:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;feat/JIRA-123-login-automation&lt;/code&gt; — new test coverage&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fix/JIRA-456-flaky-session-timeout&lt;/code&gt; — fixing an existing test&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;refactor/JIRA-789-pageobject-cleanup&lt;/code&gt; — restructuring without behavior change&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ci/JIRA-321-update-pipeline-node-version&lt;/code&gt; — CI/CD changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Short-lived. One ticket. One concern.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 2 — Commit atomically with Conventional Commits
&lt;/h3&gt;

&lt;p&gt;The format is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt;(&amp;lt;scope&amp;gt;): &amp;lt;short summary&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real examples for SDET work:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Java&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"test(checkout): add boundary tests for quantity field validation"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix(auth): correct assertion on session expiry timeout — was 5s, should be 30s"&lt;/span&gt;

&lt;span class="c"&gt;# Python&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"refactor(conftest): extract reusable login fixture to shared helpers"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"ci: upgrade Selenium Grid from 4.8 to 4.18 in docker-compose"&lt;/span&gt;

&lt;span class="c"&gt;# JavaScript/Playwright&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"test(api): add contract validation for /v2/orders response schema"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"chore(deps): update @playwright/test to 1.43.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Types used in test engineering:&lt;/strong&gt;&lt;br&gt;
| Type | When to use |&lt;br&gt;
|------|-------------|&lt;br&gt;
| &lt;code&gt;test&lt;/code&gt; | New or modified test cases |&lt;br&gt;
| &lt;code&gt;fix&lt;/code&gt; | Fixing a broken or flaky test |&lt;br&gt;
| &lt;code&gt;refactor&lt;/code&gt; | Internal restructure, no behavior change |&lt;br&gt;
| &lt;code&gt;feat&lt;/code&gt; | New test framework feature or helper |&lt;br&gt;
| &lt;code&gt;ci&lt;/code&gt; | Pipeline / GitHub Actions / Jenkins changes |&lt;br&gt;
| &lt;code&gt;chore&lt;/code&gt; | Deps, config, maintenance |&lt;br&gt;
| &lt;code&gt;docs&lt;/code&gt; | README, test plan docs |&lt;/p&gt;


&lt;h3&gt;
  
  
  Step 3 — Push early and often
&lt;/h3&gt;

&lt;p&gt;Don't sit on local commits for days. Push your branch regularly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push origin &lt;span class="nb"&gt;test&lt;/span&gt;/JIRA-512-checkout-e2e-validation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This protects your work, enables async collaboration, and means CI can catch issues before you've drifted too far.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4 — Open a PR that communicates
&lt;/h3&gt;

&lt;p&gt;A PR is a communication artifact, not just a code delivery mechanism. Use a template. Include at minimum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Summary&lt;/span&gt;
Adds E2E coverage for the checkout quantity validation edge cases per QA-512.

&lt;span class="gu"&gt;## Changes&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Added &lt;span class="sb"&gt;`CheckoutQuantityTests.java`&lt;/span&gt; with 8 test cases covering min/max/boundary inputs
&lt;span class="p"&gt;-&lt;/span&gt; Updated &lt;span class="sb"&gt;`CheckoutPage`&lt;/span&gt; POM with &lt;span class="sb"&gt;`getQuantityError()`&lt;/span&gt; helper
&lt;span class="p"&gt;-&lt;/span&gt; Fixed existing flaky assertion in &lt;span class="sb"&gt;`testCartItemRemoval`&lt;/span&gt;

&lt;span class="gu"&gt;## Test Evidence&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; ✅ All 8 new tests passing locally (Java 17, Chrome 124, Selenium 4.18)
&lt;span class="p"&gt;-&lt;/span&gt; ✅ CI run: [link to pipeline]

&lt;span class="gu"&gt;## Ticket&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;QA-512&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://yourjira/QA-512&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 5 — Review test code like it's real code
&lt;/h3&gt;

&lt;p&gt;Because it is.&lt;/p&gt;

&lt;p&gt;A peer review of test code should check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are assertions actually asserting the right thing? (Not just &lt;code&gt;assertNotNull(response)&lt;/code&gt; everywhere)&lt;/li&gt;
&lt;li&gt;Are there hardcoded waits hiding race conditions? (&lt;code&gt;Thread.sleep(3000)&lt;/code&gt; is a smell)&lt;/li&gt;
&lt;li&gt;Is the test independent, or does it depend on test order?&lt;/li&gt;
&lt;li&gt;Does the naming clearly describe what the test validates?&lt;/li&gt;
&lt;li&gt;Are page objects/fixtures being reused, or is logic being duplicated?&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 6 — Let CI be the gatekeeper
&lt;/h3&gt;

&lt;p&gt;Configure your test repo the same way a production repo would be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Branch protection on &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;develop&lt;/code&gt; — no direct pushes&lt;/li&gt;
&lt;li&gt;✅ Require at least 1 reviewer approval before merge&lt;/li&gt;
&lt;li&gt;✅ Require CI to be green before merge&lt;/li&gt;
&lt;li&gt;✅ Use a &lt;code&gt;PULL_REQUEST_TEMPLATE.md&lt;/code&gt; in &lt;code&gt;.github/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;✅ Add &lt;code&gt;CODEOWNERS&lt;/code&gt; so reviewers are auto-assigned
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/CODEOWNERS&lt;/span&gt;
&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="s"&gt;.java   @your-team/sdet-java&lt;/span&gt;
&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="s"&gt;.py     @your-team/sdet-python&lt;/span&gt;
&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="s"&gt;.spec.ts @your-team/sdet-playwright&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 7 — Merge clean, tag releases, delete branches
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Squash merge keeps history clean&lt;/span&gt;
git merge &lt;span class="nt"&gt;--squash&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;/JIRA-512-checkout-e2e-validation

&lt;span class="c"&gt;# Tag test suite releases to align with app versions&lt;/span&gt;
git tag &lt;span class="nt"&gt;-a&lt;/span&gt; v2.4.1-tests &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Test coverage for release 2.4.1"&lt;/span&gt;

&lt;span class="c"&gt;# Delete merged branches&lt;/span&gt;
git branch &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;/JIRA-512-checkout-e2e-validation
git push origin &lt;span class="nt"&gt;--delete&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;/JIRA-512-checkout-e2e-validation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Recommended &lt;code&gt;.github&lt;/code&gt; Folder Setup for Test Repos
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.github/
├── PULL_REQUEST_TEMPLATE.md     # Enforces PR quality
├── CODEOWNERS                   # Auto-assign reviewers
└── workflows/
    ├── ci.yml                   # Run tests on every PR
    └── lint.yml                 # Lint Java/Python/JS test code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Mindset Shift
&lt;/h2&gt;

&lt;p&gt;Here's the reframe that matters most:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;You are a software engineer who specializes in quality. That means the quality bar applies to everything you build — including your test code.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next time you're about to commit with a message of &lt;code&gt;fix2&lt;/code&gt; or push directly to main because it's faster, ask yourself: &lt;em&gt;Would I accept this in a PR from a developer I'm reviewing?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If the answer is no, hold yourself to the same standard.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Reference Cheat Sheet
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ✅ Start a new piece of work&lt;/span&gt;
git checkout develop
git pull origin develop
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;/TICKET-123-feature-name

&lt;span class="c"&gt;# ✅ Commit atomically&lt;/span&gt;
git add src/test/java/com/app/CheckoutTests.java
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"test(checkout): add edge case coverage for promo code validation"&lt;/span&gt;

&lt;span class="c"&gt;# ✅ Keep your branch current&lt;/span&gt;
git fetch origin
git rebase origin/develop

&lt;span class="c"&gt;# ✅ Push and open PR&lt;/span&gt;
git push origin &lt;span class="nb"&gt;test&lt;/span&gt;/TICKET-123-feature-name
&lt;span class="c"&gt;# → Open PR via GitHub UI with template&lt;/span&gt;

&lt;span class="c"&gt;# ✅ After merge, clean up&lt;/span&gt;
git checkout develop
git pull origin develop
git branch &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;/TICKET-123-feature-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;The discipline gap in QA version control is one of the most fixable problems in our space.&lt;/strong&gt; It doesn't require new tools, new frameworks, or budget approval. It requires a decision — made individually and then reinforced as a team — that test code deserves the same care as the code it validates.&lt;/p&gt;

&lt;p&gt;Start with your next commit.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Are you an SDET or QA engineer who's either guilty of these patterns or has successfully fixed them on your team? Drop your experience in the comments — I'd love to hear what worked.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;#testing #github #sdet #devops #qualityengineering #automation #git&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>github</category>
      <category>sdet</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
