Module 1: Introduction to Git and Version Control for Testing

Understand why version control is critical for test automation projects. Learn the fundamental concepts of Git, set up your environment, and make your first commits with test scripts. Explore how Git solves common problems test engineers face: tracking changes in test cases, collaborating on automation frameworks, and maintaining test data.

Why Test Engineers Need Git: Tracking Your Test Automation Journey

Why This Matters

The Test Automation Chaos Problem

Imagine this: You’ve spent weeks building a robust test automation suite. Everything works perfectly. Then, a week later, tests start failing mysteriously. What changed? You try to remember—was it the login test you modified? The test data you updated? Or maybe that framework refactoring you did three days ago?

Without version control, you’re stuck. You might have a folder called test_scripts_backup_final_v2_REALLY_FINAL (we’ve all been there), but you can’t remember what changed between versions or why you made those changes.

This is the reality for test engineers working without Git. You face:

  • Lost work: Accidentally overwriting test scripts with no way to recover previous versions
  • Collaboration nightmares: Multiple team members editing the same test file, manually merging changes via email or shared drives
  • Mystery failures: Tests break and you can’t identify what changed or when
  • Audit gaps: No record of who modified test data or why critical test cases were removed
  • Framework evolution chaos: Unable to track how your automation framework evolved or revert problematic changes

When You’ll Use This Skill

Git isn’t just for developers—it’s a fundamental tool for modern test engineers. You’ll use Git daily when you:

  • Write and maintain automated test scripts (Selenium, Cypress, Playwright, etc.)
  • Update test data files (JSON, CSV, XML)
  • Modify automation frameworks and utilities
  • Collaborate with other test engineers or developers
  • Document test approaches and configurations
  • Share test automation code during code reviews
  • Deploy tests to CI/CD pipelines
  • Investigate when and why tests started failing

Whether you’re working solo on a small project or part of a large QA team, Git provides the safety net and collaboration foundation you need.

Pain Points Git Solves

For Individual Test Engineers:

  • Track every change to your test scripts with complete history
  • Experiment safely—try new approaches knowing you can always go back
  • Understand your own work from weeks or months ago

For Test Teams:

  • Work on the same automation framework without stepping on each other’s toes
  • Review each other’s test code before it goes live
  • Maintain a single source of truth for all test assets

For Test Automation Projects:

  • Keep test code, test data, and configurations synchronized
  • Create reproducible test environments
  • Integrate seamlessly with CI/CD tools like Jenkins, GitHub Actions, or GitLab CI

What You’ll Accomplish in This Lesson

By the end of this lesson, you’ll transform from someone who manages test scripts in folders to someone who professionally tracks and manages test automation assets using industry-standard tools.

Your Learning Journey

First, you’ll understand the “why” behind version control. We’ll explore real scenarios test engineers face and see how Git provides solutions. You’ll learn the core concepts that make Git work—repositories, commits, and tracking—without getting lost in jargon.

Next, you’ll install and configure Git on your machine. We’ll walk through the complete setup process for Windows, Mac, or Linux, and configure Git with your identity and preferences. This is hands-on—you’ll actually set up your Git environment.

Then, you’ll create your first test repository. You’ll initialize a real test automation project, understanding what happens behind the scenes when you turn a folder into a Git repository.

After that, you’ll track actual test scripts. You’ll add test files, make your first commits, and see how Git captures snapshots of your work. We’ll use realistic test automation examples so you can immediately apply this to your projects.

Finally, you’ll solve real test engineering problems using Git. We’ll tackle scenarios like tracking test case changes over time, managing test data files, and handling framework modifications—all the challenges that make version control critical for test automation.

Hands-On Approach

This isn’t a theory lesson. You’ll be typing commands, creating files, and seeing results. Every concept comes with practical examples using test automation scenarios you’ll recognize. By the lesson’s end, you’ll have a working test repository and the confidence to start using Git in your daily testing work.

Let’s begin your Git journey and take control of your test automation projects! 🚀


Core Content

Core Content

Core Concepts Explained

What is Version Control and Why Git Matters for Test Engineers

Version control is a system that tracks changes to files over time. Think of it as a “time machine” for your code that lets you:

  • See what changed, when, and by whom
  • Revert to previous versions if something breaks
  • Work on different features simultaneously
  • Collaborate with team members without overwriting each other’s work

Git is the most popular version control system, and it’s essential for test automation because:

  1. Test Code is Code: Your automation scripts need the same care as production code
  2. Collaboration: Multiple testers can work on different test suites simultaneously
  3. Traceability: Link test changes to specific application versions or bug fixes
  4. Safety Net: Quickly recover if a test refactor goes wrong
  5. CI/CD Integration: Modern pipelines require Git to automatically run your tests

How Git Works: The Three States

Git tracks your test files through three main states:

graph LR
    A[Working Directory<br/>Your test files] -->|git add| B[Staging Area<br/>Files ready to commit]
    B -->|git commit| C[Repository<br/>Permanent snapshot]
    C -->|git checkout| A
  • Working Directory: Where you write and modify your test code
  • Staging Area: Where you prepare files before saving a snapshot
  • Repository: Where Git permanently stores snapshots of your work

Step-by-Step: Installing Git

Windows Installation

  1. Download Git from git-scm.com

  2. Run the installer with these recommended settings:

    • Use Git from Git Bash and also from Windows Command Prompt
    • Use default line ending conversions
    • Use MinTTY as terminal emulator
  3. Verify installation:

$ git --version
git version 2.42.0

macOS Installation

Using Homebrew (recommended):

$ brew install git

Or download from git-scm.com

Verify:

$ git --version
git version 2.42.0

Linux Installation

Ubuntu/Debian:

$ sudo apt-get update
$ sudo apt-get install git

Fedora/RHEL:

$ sudo dnf install git

Verify:

$ git --version
git version 2.42.0

Step-by-Step: Configuring Git

After installation, configure your identity. This information appears in every commit you make:

# Set your name
$ git config --global user.name "Your Name"

# Set your email
$ git config --global user.email "your.email@example.com"

# Set default branch name to 'main'
$ git config --global init.defaultBranch main

# Verify your configuration
$ git config --list
user.name=Your Name
user.email=your.email@example.com
init.defaultbranch=main

Optional but recommended configurations:

# Enable colored output for better readability
$ git config --global color.ui auto

# Set your default editor (example: VS Code)
$ git config --global core.editor "code --wait"

# Set up line endings (Windows)
$ git config --global core.autocrlf true

# Set up line endings (Mac/Linux)
$ git config --global core.autocrlf input

Step-by-Step: Initializing Your First Test Repository

Creating a New Repository

Let’s create a repository for a Playwright test project:

# Create project directory
$ mkdir ecommerce-tests
$ cd ecommerce-tests

# Initialize Git repository
$ git init
Initialized empty Git repository in /Users/yourname/ecommerce-tests/.git/

# Verify repository creation
$ ls -la
drwxr-xr-x   .git/

Understanding the .git Directory

The .git directory contains all version control information. Never manually modify this directory.

$ ls .git/
HEAD
config
objects/
refs/

Step-by-Step: Creating Your First Test and Committing

1. Create a Test File

Create a simple Playwright test:

// tests/login.spec.js
const { test, expect } = require('@playwright/test');

test('user can login successfully', async ({ page }) => {
  // Navigate to login page
  await page.goto('https://practiceautomatedtesting.com/login');
  
  // Fill in credentials
  await page.fill('#username', 'testuser@example.com');
  await page.fill('#password', 'Test123!');
  
  // Click login button
  await page.click('button[type="submit"]');
  
  // Verify successful login
  await expect(page).toHaveURL(/dashboard/);
});

2. Check Repository Status

$ git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        tests/

nothing added to commit but untracked files present (use "git add" to track)

Git sees your new file but isn’t tracking it yet.

3. Stage Your Changes

# Add specific file
$ git add tests/login.spec.js

# Or add all files in directory
$ git add tests/

# Check status again
$ git status
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   tests/login.spec.js

4. Create Your First Commit

$ git commit -m "Add login test for practice site"
[main (root-commit) a3f7d9c] Add login test for practice site
 1 file changed, 15 insertions(+)
 create mode 100644 tests/login.spec.js

Commit message best practices:

  • Use present tense: “Add test” not “Added test”
  • Be descriptive: “Add login validation test” vs “Update tests”
  • Keep first line under 50 characters
  • Add details in body if needed (leave blank line after first line)

5. View Commit History

$ git log
commit a3f7d9c8f2e1b4a7c9d3e5f6a8b2c4d6e8f0a1b3
Author: Your Name <your.email@example.com>
Date:   Mon Jan 15 10:30:45 2024 -0800

    Add login test for practice site

# One-line format for cleaner view
$ git log --oneline
a3f7d9c Add login test for practice site

Practical Example: A Complete Test Automation Workflow

Let’s walk through a realistic scenario: adding a new checkout test.

Step 1: Create the Test

// tests/checkout.spec.js
const { test, expect } = require('@playwright/test');

test.describe('Checkout Process', () => {
  test('user can complete purchase', async ({ page }) => {
    // Add product to cart
    await page.goto('https://practiceautomatedtesting.com/products');
    await page.click('.product-item:first-child .add-to-cart');
    
    // Navigate to checkout
    await page.click('.cart-icon');
    await page.click('button:has-text("Proceed to Checkout")');
    
    // Fill shipping information
    await page.fill('#shipping-name', 'John Doe');
    await page.fill('#shipping-address', '123 Test Street');
    await page.fill('#shipping-city', 'Test City');
    await page.fill('#shipping-zip', '12345');
    
    // Complete payment
    await page.fill('#card-number', '4242424242424242');
    await page.fill('#card-expiry', '12/25');
    await page.fill('#card-cvc', '123');
    await page.click('button:has-text("Place Order")');
    
    // Verify success
    await expect(page.locator('.success-message')).toBeVisible();
    await expect(page.locator('.order-confirmation')).toContainText('Thank you');
  });
});

Step 2: Create a .gitignore File

Before committing, exclude files that shouldn’t be tracked:

# .gitignore
node_modules/
test-results/
playwright-report/
.env
*.log
.DS_Store

Step 3: Stage and Commit Everything

$ git status
On branch main
Untracked files:
  .gitignore
  tests/checkout.spec.js

$ git add .gitignore tests/checkout.spec.js

$ git commit -m "Add checkout test with payment validation

- Tests complete purchase flow
- Validates shipping information form
- Verifies payment processing
- Checks order confirmation message"

Step 4: View Your Progress

$ git log --oneline
b7e2f8a Add checkout test with payment validation
a3f7d9c Add login test for practice site

Using Git: Common Daily Commands

Checking What Changed

# See modified files
$ git status

# See actual changes in files (before staging)
$ git diff

# See changes in staged files
$ git diff --staged

Example: Modifying a Test

// Before: tests/login.spec.js
test('user can login successfully', async ({ page }) => {
  await page.goto('https://practiceautomatedtesting.com/login');
  await page.fill('#username', 'testuser@example.com');
  await page.fill('#password', 'Test123!');
  await page.click('button[type="submit"]');
  await expect(page).toHaveURL(/dashboard/);
});
// After: tests/login.spec.js
test('user can login successfully', async ({ page }) => {
  await page.goto('https://practiceautomatedtesting.com/login');
  
  // Updated selectors for new login form
  await page.fill('[data-testid="email-input"]', 'testuser@example.com');
  await page.fill('[data-testid="password-input"]', 'Test123!');
  await page.click('[data-testid="login-button"]');
  
  // More specific assertion
  await expect(page.locator('.dashboard-header')).toBeVisible();
  await expect(page.locator('.user-profile')).toContainText('testuser');
});

Check the changes:

$ git diff tests/login.spec.js
diff --git a/tests/login.spec.js b/tests/login.spec.js
@@ -2,8 +2,12 @@ test('user can login successfully', async ({ page }) => {
   await page.goto('https://practiceautomatedtesting.com/login');
-  await page.fill('#username', 'testuser@example.com');
-  await page.fill('#password', 'Test123!');
-  await page.click('button[type="submit"]');
-  await expect(page).toHaveURL(/dashboard/);
+  
+  // Updated selectors for new login form
+  await page.fill('[data-testid="email-input"]', 'testuser@example.com');
+  await page.fill('[data-testid="password-input"]', 'Test123!');
+  await page.click('[data-testid="login-button"]');
+  
+  // More specific assertion
+  await expect(page.locator('.dashboard-header')).toBeVisible();
+  await expect(page.locator('.user-profile')).toContainText('testuser');
 });

Commit the update:

$ git add tests/login.spec.js
$ git commit -m "Update login test to use data-testid selectors"

Viewing History and Changes

# View commit history
$ git log --oneline --graph
* c9d4e5f Update login test to use data-testid selectors
* b7e2f8a Add checkout test with payment validation
* a3f7d9c Add login test for practice site

# See what changed in a specific commit
$ git show c9d4e5f

# View history of a specific file
$ git log --oneline tests/login.spec.js
c9d4e5f Update login test to use data-testid selectors
a3f7d9c Add login test for practice site

Common Mistakes and How to Avoid Them

Mistake 1: Forgetting to Configure Git

Problem:

$ git commit -m "Add test"
*** Please tell me who you are.
fatal: unable to auto-detect email address

Solution:

$ git config --global user.name "Your Name"
$ git config --global user.email "your.email@example.com"

Mistake 2: Committing Without Staging

Problem:

$ git commit -m "Add new test"
On branch main
Untracked files:
        tests/new-test.spec.js

nothing added to commit but untracked files present

Solution: Always use git add first:

$ git add tests/new-test.spec.js
$ git commit -m "Add new test"

Mistake 3: Committing Sensitive Data

Problem: Accidentally committing passwords, API keys, or credentials:

// WRONG!
const API_KEY = 'sk_live_abc123xyz789';

Solution: Use .gitignore and environment variables:

# .gitignore
.env
secrets.json
// CORRECT!
const API_KEY = process.env.API_KEY;

Mistake 4: Poor Commit Messages

Bad:

$ git commit -m "fix"
$ git commit -m "updates"
$ git commit -m "asdfgh"

Good:

$ git commit -m "Fix login test selector for email field"
$ git commit -m "Update checkout test to handle new payment modal"
$ git commit -m "Add smoke tests for critical user flows"

Mistake 5: Committing node_modules or Test Reports

Problem: Huge commits with thousands of dependency files.

Solution: Always create .gitignore before first commit:

# .gitignore
node_modules/
test-results/
playwright-report/
allure-report/
coverage/
*.log

Debugging: How to Undo Mistakes

Undo changes before staging:

# Discard changes in a specific file
$ git checkout -- tests/login.spec.js

# Discard all changes
$ git checkout -- .

Unstage files (keep changes):

$ git reset HEAD tests/login.spec.js

Amend last commit (fix message or add forgotten files):

$ git add tests/forgotten-file.spec.js
$ git commit --amend -m "Add login and validation tests"

Check what you’re about to commit:

# Always review before committing
$ git diff --staged

Quick Reference: Essential Commands

# Setup (one-time)
git config --global user.name "Your Name"
git config --global user.email "your@email.com"

# Starting a project
git init                          # Initialize repository

# Daily workflow
git status                        # Check what changed
git add <file>                    # Stage specific file
git add .                         # Stage all changes
git commit -m "message"           # Save snapshot
git log --oneline                 # View history
git diff                          # See unstaged changes
git diff --staged                 # See staged changes

# Checking history
git log                           # Full history
git log --oneline --graph         # Visual history
git show <commit-id>              # See specific commit

This foundation prepares you to track your test automation work effectively. In the next lessons, you’ll learn about branching, remote repositories, and collaborative workflows.


Hands-On Practice

Hands-On Exercise

🎯 Exercise: Create Your First Test Automation Repository

In this exercise, you’ll set up a Git repository for a simple test automation project and practice the fundamental Git workflow that test engineers use daily.

Task

Create a Git repository, add test files, make changes, and track your automation journey using basic Git commands.

Prerequisites

  • Git installed on your computer
  • A text editor (VS Code, Notepad++, or any editor)
  • Terminal/Command Prompt access

Step-by-Step Instructions

Step 1: Initialize Your Test Repository

# Create a new directory for your test project
mkdir my-first-test-automation
cd my-first-test-automation

# Initialize Git repository
git init

# Verify Git is tracking this folder
git status

Step 2: Create Your First Test File

Create a file named test_login.py with the following content:

# test_login.py
def test_valid_login():
    # TODO: Add test for valid credentials
    pass

def test_invalid_login():
    # TODO: Add test for invalid credentials
    pass

Step 3: Add and Commit Your First Test

# Check the status (you should see untracked files)
git status

# Add the file to staging area
git add test_login.py

# Commit with a descriptive message
git commit -m "Add initial login test cases"

# View your commit history
git log

Step 4: Make Changes to Your Test

Update test_login.py to implement one test:

# test_login.py
def test_valid_login():
    username = "testuser@example.com"
    password = "SecurePass123"
    # Simulate login validation
    assert username and password, "Login should succeed with valid credentials"

def test_invalid_login():
    # TODO: Add test for invalid credentials
    pass

Step 5: Track Your Changes

# See what changed
git diff

# Stage and commit the changes
git add test_login.py
git commit -m "Implement valid login test case"

Step 6: Add Test Documentation

Create a README.md file:

# Login Test Suite

## Test Cases
- test_valid_login: Verifies successful login with correct credentials
- test_invalid_login: Verifies error handling with wrong credentials

## How to Run
Coming soon...

Step 7: Commit Multiple Files

# Add all files at once
git add .

# Commit with descriptive message
git commit -m "Add test documentation"

# View your complete history
git log --oneline

Step 8: Create a .gitignore File

Create .gitignore to exclude unnecessary files:

# Python
__pycache__/
*.pyc
*.pyo

# Test Reports
reports/
*.log

# IDE
.vscode/
.idea/
git add .gitignore
git commit -m "Add gitignore for Python test project"

Expected Outcome

By the end of this exercise, you should have:

  • ✅ A Git repository initialized in your test project folder
  • ✅ At least 4 commits in your history
  • ✅ A test file, README, and .gitignore tracked by Git
  • ✅ Understanding of the basic Git workflow: modify → add → commit
  • ✅ Ability to check status and view history

Verification Commands

# Verify you have multiple commits
git log --oneline

# Should show at least 4 commits:
# - Add initial login test cases
# - Implement valid login test case
# - Add test documentation
# - Add gitignore for Python test project

# Verify all files are tracked
git ls-files

# Should show: test_login.py, README.md, .gitignore

Bonus Challenge 🌟

  1. Implement the test_invalid_login() function
  2. Create a new file test_logout.py with logout test cases
  3. Make at least 2 more commits with meaningful messages
  4. Use git log --oneline --graph to visualize your commit history

Key Takeaways

🔑 Essential Points to Remember:

  • Version Control is Essential for Test Automation: Git tracks every change to your test scripts, allowing you to see what changed, when, and why—critical for maintaining test suites over time.

  • The Basic Git Workflow: The core cycle every test engineer uses is: make changes → check status (git status) → stage files (git add) → commit with message (git commit -m) → review history (git log).

  • Meaningful Commit Messages Matter: Descriptive commit messages like “Add validation for empty password field” are far more valuable than vague ones like “updated tests” when debugging or reviewing test changes months later.

  • Git Tracks Files, Not Folders: You must explicitly tell Git which files to track using git add, and you can exclude generated files (like test reports or logs) using .gitignore.

  • Your Repository is Your Test History: Your commit history becomes a complete log of your testing journey—documenting what tests were added, modified, or removed, making it easier to collaborate with other QA engineers and developers.


Next Steps

🎯 What to Practice

  1. Daily Git Habit: For the next week, create a Git repository for any small test project and make at least one commit daily
  2. Descriptive Commits: Practice writing clear, specific commit messages that explain what and why
  3. Explore History: Use git log, git diff, and git show to examine your test changes
  4. Clean Repositories: Practice creating .gitignore files for different test frameworks (Selenium, Playwright, etc.)

Immediate Next Steps:

  • Branching: Learn to create branches for new test features (git branch, git checkout)
  • Remote Repositories: Push your tests to GitHub/GitLab for backup and collaboration
  • Undoing Changes: Learn to revert mistakes with git checkout, git reset, and git revert

Intermediate Topics:

  • Collaborating with Developers: Pull requests and code reviews for test automation
  • CI/CD Integration: Connecting your Git repository to automated test runs
  • Git for Test Data: Managing test data files and configuration with version control

Resources:

  • GitHub’s “Hello World” guide for practicing with remote repositories
  • Git branching tutorials for managing test feature development
  • Your team’s Git workflow documentation (if available)

🎉 Congratulations! You’ve taken your first step into version-controlled test automation. Git will become one of your most valuable tools as a test engineer!