Module 3: Branching and Switching: Isolated Test Development

Learn to create and manage branches for developing new test features, fixing bugs, and experimenting with test frameworks without affecting the main test suite. Understand branch strategies specific to test automation projects and practice switching between different testing contexts.

Creating Your First Test Feature Branch

Why This Matters

Imagine you’re working on a critical test automation suite that runs continuously in your CI/CD pipeline. Your team depends on these tests to catch bugs before they reach production. Now, you need to add a new test feature or experiment with a different assertion library. If you make changes directly to the main branch and something breaks, you’ve just disrupted everyone’s workflow and potentially blocked deployments.

This is the exact problem branches solve.

In real-world test automation projects, you’ll constantly face scenarios like:

  • Adding new test cases for upcoming features without breaking existing tests
  • Experimenting with new testing frameworks (like switching from unittest to pytest) without risking your stable test suite
  • Fixing flaky tests in isolation while others continue working
  • Updating test dependencies that might introduce breaking changes
  • Creating proof-of-concept tests to validate new testing approaches

Without branches, every change you make directly affects your entire team. Tests that were passing might suddenly fail. Your CI/CD pipeline could break. Other team members might pull your half-finished work and waste time debugging issues that aren’t even their responsibility.

Branches give you a safe sandbox to develop, experiment, and validate your test changes before they impact anyone else. They’re not just a nice-to-have feature—they’re an essential professional practice that separates chaotic test development from disciplined, collaborative test engineering.

What You’ll Learn

By the end of this lesson, you’ll have hands-on experience creating and managing branches specifically for test automation work. This isn’t just theory—you’ll actually create branches, switch between them, and understand how they protect your test suite’s stability.

Here’s How We’ll Cover Each Objective:

Understanding why branches matter for test automation: We’ll start by exploring real test automation scenarios where branches prevent disasters. You’ll see concrete examples of how branches isolate changes and protect your main test suite.

Creating feature branches: You’ll learn the exact Git commands to create new branches for test development. We’ll walk through creating your first branch step-by-step, and you’ll understand what happens behind the scenes when you create a branch.

Switching between branches: You’ll practice moving between different branches, experiencing how Git changes your working directory to match each branch’s context. This skill lets you quickly shift between different test development tasks.

Using test-specific naming conventions: We’ll introduce branch naming patterns designed for test automation projects—patterns that make it instantly clear whether a branch contains new test features, bug fixes, or experimental framework changes. You’ll learn conventions that improve team communication.

Maintaining branch isolation: Finally, you’ll understand how to keep your test branches completely separate from the main suite, ensuring that experimental or in-progress changes never accidentally affect stable tests running in production environments.

Each concept builds on the previous one, giving you a complete mental model of how branching works in test automation contexts. By the lesson’s end, you’ll be confident creating branches for any test development scenario.


Core Content

Core Content: Creating Your First Test Feature Branch

1. Core Concepts Explained

Understanding Feature Branches in Test Automation

A feature branch is an isolated line of development where you can work on new test cases, update existing tests, or experiment with automation frameworks without affecting the main codebase. Think of it as your personal workspace where mistakes won’t break anything for your team.

Why Feature Branches Matter for Test Automation:

  • Isolation: Your test changes don’t interfere with working tests on the main branch
  • Collaboration: Multiple testers can work on different test suites simultaneously
  • Review Process: Changes can be reviewed before merging into the main test suite
  • Rollback Safety: Easy to discard changes that don’t work out

The Feature Branch Workflow

graph LR
    A[Main Branch] --> B[Create Feature Branch]
    B --> C[Write Tests]
    C --> D[Commit Changes]
    D --> E[Push to Remote]
    E --> F[Create Pull Request]
    F --> G[Merge to Main]
    G --> A

Basic Git Commands for Branching

Before diving into feature branches, let’s understand the essential Git commands:

  1. git branch - Lists, creates, or deletes branches
  2. git checkout - Switches between branches
  3. git checkout -b - Creates and switches to a new branch in one command
  4. git status - Shows the current state of your working directory
  5. git push - Uploads local branch commits to remote repository

2. Step-by-Step: Creating Your First Test Feature Branch

Step 1: Check Your Current Branch

Before creating a new branch, verify which branch you’re currently on:

$ git branch
* main
  develop

The asterisk (*) indicates your current branch. Always create feature branches from an updated main or develop branch.

Step 2: Update Your Main Branch

Ensure you have the latest changes from the remote repository:

$ git checkout main
Switched to branch 'main'

$ git pull origin main
Already up to date.
# Expected output when updates are available:
$ git pull origin main
remote: Counting objects: 5, done.
Unpacking objects: 100% (5/5), done.
From https://github.com/username/test-automation-repo
 * branch            main       -> FETCH_HEAD
Updating a1b2c3d..e4f5g6h
Fast-forward
 tests/login.spec.js | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

Step 3: Create Your Feature Branch

Use a descriptive naming convention. Common patterns for test automation branches:

  • test/feature-name - For new test features
  • test/bug-fix-123 - For test fixes (with issue number)
  • test/update-login-tests - For updating existing tests
$ git checkout -b test/add-login-tests
Switched to a new branch 'test/add-login-tests'

This command does two things:

  1. Creates a new branch called test/add-login-tests
  2. Switches to that branch automatically

Step 4: Verify Your New Branch

Confirm you’re on the new branch:

$ git branch
  main
* test/add-login-tests

$ git status
On branch test/add-login-tests
nothing to commit, working tree clean

3. Practical Example: Creating a Login Test on a Feature Branch

Let’s create a complete example using Playwright and practiceautomatedtesting.com:

Create the Test File

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

test.describe('Login Functionality Tests', () => {
  
  test.beforeEach(async ({ page }) => {
    // Navigate to the practice site before each test
    await page.goto('https://practiceautomatedtesting.com/');
  });

  test('should successfully login with valid credentials', async ({ page }) => {
    // Click on account/login link
    await page.click('text=Account');
    
    // Fill in login credentials
    await page.fill('#username', 'testuser@example.com');
    await page.fill('#password', 'SecurePassword123');
    
    // Click login button
    await page.click('button[type="submit"]');
    
    // Verify successful login
    await expect(page.locator('.welcome-message')).toBeVisible();
    await expect(page.locator('.welcome-message')).toContainText('Welcome');
  });

  test('should show error message with invalid credentials', async ({ page }) => {
    // Navigate to login page
    await page.click('text=Account');
    
    // Attempt login with invalid credentials
    await page.fill('#username', 'invalid@example.com');
    await page.fill('#password', 'wrongpassword');
    await page.click('button[type="submit"]');
    
    // Verify error message appears
    await expect(page.locator('.error-message')).toBeVisible();
    await expect(page.locator('.error-message'))
      .toContainText('Invalid username or password');
  });

  test('should validate required fields', async ({ page }) => {
    // Navigate to login page
    await page.click('text=Account');
    
    // Try to submit without filling fields
    await page.click('button[type="submit"]');
    
    // Verify validation messages
    await expect(page.locator('#username-error')).toBeVisible();
    await expect(page.locator('#password-error')).toBeVisible();
  });
});

Step 5: Check Status of Your Changes

$ git status
On branch test/add-login-tests
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        tests/login.spec.js

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

Step 6: Stage Your Changes

$ git add tests/login.spec.js

$ git status
On branch test/add-login-tests
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   tests/login.spec.js

Step 7: Commit Your Changes

Write a clear, descriptive commit message:

$ git commit -m "Add comprehensive login tests for authentication flows"
[test/add-login-tests a1b2c3d] Add comprehensive login tests for authentication flows
 1 file changed, 45 insertions(+)
 create mode 100644 tests/login.spec.js

Commit Message Best Practices:

  • Use present tense (“Add tests” not “Added tests”)
  • Be descriptive but concise
  • Reference issue numbers when applicable: "Add login tests - fixes #123"

Step 8: Push Your Feature Branch to Remote

$ git push origin test/add-login-tests
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 1.2 KiB | 1.2 MiB/s, done.
Total 4 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/username/test-automation-repo.git
 * [new branch]      test/add-login-tests -> test/add-login-tests

Step 9: Making Additional Changes

If you need to add more tests or make changes:

// tests/login.spec.js - Adding a new test
test('should allow password visibility toggle', async ({ page }) => {
  await page.click('text=Account');
  
  // Type password
  await page.fill('#password', 'SecurePassword123');
  
  // Verify password is hidden
  await expect(page.locator('#password')).toHaveAttribute('type', 'password');
  
  // Click visibility toggle
  await page.click('.toggle-password-visibility');
  
  // Verify password is now visible
  await expect(page.locator('#password')).toHaveAttribute('type', 'text');
});

Commit and push the changes:

$ git add tests/login.spec.js
$ git commit -m "Add password visibility toggle test"
$ git push origin test/add-login-tests

4. Working with Multiple Branches

Switching Between Branches

# Switch back to main
$ git checkout main
Switched to branch 'main'

# Create another test branch
$ git checkout -b test/add-checkout-tests
Switched to a new branch 'test/add-checkout-tests'

# Switch back to your login tests branch
$ git checkout test/add-login-tests
Switched to branch 'test/add-login-tests'

Viewing All Branches

$ git branch -a
  main
* test/add-login-tests
  test/add-checkout-tests
  remotes/origin/main
  remotes/origin/test/add-login-tests

5. Common Mistakes and How to Avoid Them

Mistake 1: Creating a Branch from the Wrong Starting Point

Problem:

# Creating a feature branch while on another feature branch
$ git branch
* test/broken-feature
  main

$ git checkout -b test/new-feature  # ❌ This branches from test/broken-feature!

Solution:

# Always check out main (or develop) first
$ git checkout main
$ git pull origin main
$ git checkout -b test/new-feature  # ✅ Now branching from updated main

Mistake 2: Forgetting to Commit Before Switching Branches

Problem:

$ git checkout main
error: Your local changes to the following files would be overwritten by checkout:
        tests/login.spec.js
Please commit your changes or stash them before you switch branches.

Solution:

# Option 1: Commit your changes
$ git add tests/login.spec.js
$ git commit -m "WIP: Login tests in progress"
$ git checkout main

# Option 2: Stash your changes (temporary save)
$ git stash
Saved working directory and index state WIP on test/add-login-tests
$ git checkout main
# Later, return to your branch and restore changes
$ git checkout test/add-login-tests
$ git stash pop

Mistake 3: Poor Branch Naming

Bad Examples:

  • test (too vague)
  • my-branch (not descriptive)
  • asdf (meaningless)
  • john-test-branch (includes personal name)

Good Examples:

  • test/add-login-validation
  • test/fix-checkout-timeout
  • test/update-api-tests
  • test/refactor-page-objects

Mistake 4: Not Pulling Latest Changes Before Creating Branch

Problem: Your branch is based on outdated code, leading to merge conflicts later.

Solution:

# Always pull before branching
$ git checkout main
$ git pull origin main  # Get latest changes
$ git checkout -b test/new-feature

Mistake 5: Pushing to Wrong Branch

Problem:

$ git push origin main  # ❌ Accidentally pushing to main instead of feature branch

Solution:

# Always verify your current branch
$ git branch
* test/add-login-tests

# Push to the correct branch
$ git push origin test/add-login-tests

# Or use this shortcut (pushes current branch)
$ git push origin HEAD

6. Quick Reference: Feature Branch Workflow

# 1. Start from main
git checkout main
git pull origin main

# 2. Create feature branch
git checkout -b test/descriptive-name

# 3. Make changes, then check status
git status

# 4. Stage changes
git add path/to/test-file.js

# 5. Commit with message
git commit -m "Add descriptive message"

# 6. Push to remote
git push origin test/descriptive-name

# 7. Continue working (repeat steps 3-6 as needed)

# 8. When done, create Pull Request on GitHub/GitLab

7. Next Steps

After creating your feature branch and pushing your tests:

  1. Create a Pull Request - Request to merge your tests into the main branch
  2. Run CI/CD Tests - Automated tests will run on your branch
  3. Request Code Review - Team members review your test code
  4. Address Feedback - Make requested changes and push updates
  5. Merge - Once approved, merge your tests into main

Your feature branch workflow is now complete! This process ensures your test automation changes are organized, reviewable, and safely integrated into your project.


Hands-On Practice

EXERCISE

Hands-On Exercise: Create Your Test Feature Branch

Task

Create a new feature branch for adding login tests to a test automation project, make changes to a test file, commit your work, and push it to the remote repository.

Prerequisites

  • Git installed on your machine
  • Access to a test automation repository (or create a new one)
  • Basic understanding of command line/terminal

Step-by-Step Instructions

Step 1: Clone or Navigate to Your Repository

# If you don't have a repo yet, create a new directory
mkdir test-automation-practice
cd test-automation-practice
git init

# Or navigate to your existing project
cd your-test-project

Step 2: Check Current Branch and Status

git status
git branch

Step 3: Create and Switch to a New Feature Branch

# Create a new branch for your login tests feature
git checkout -b feature/login-tests

# Verify you're on the new branch
git branch

Step 4: Create or Modify a Test File

# Create a new test file
touch tests/login_test.py

Add the following starter code to tests/login_test.py:

# tests/login_test.py
import unittest

class LoginTest(unittest.TestCase):
    
    def test_successful_login(self):
        """Test successful login with valid credentials"""
        # TODO: Add your test implementation
        username = "testuser"
        password = "password123"
        self.assertEqual(username, "testuser")
    
    def test_invalid_password(self):
        """Test login fails with invalid password"""
        # TODO: Add your test implementation
        self.assertTrue(True)

if __name__ == '__main__':
    unittest.main()

Step 5: Stage and Commit Your Changes

# Check what files have changed
git status

# Stage your new test file
git add tests/login_test.py

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

Step 6: Push Your Feature Branch

# Push the branch to remote repository
git push origin feature/login-tests

# If this is your first push, you may need to set upstream
git push -u origin feature/login-tests

Step 7: Verify Your Work

# View your commit history
git log --oneline

# Check your branch status
git status

Expected Outcome

After completing this exercise, you should have:

✅ A new feature branch named feature/login-tests
✅ A test file (login_test.py) with basic test cases
✅ At least one commit with a clear message
✅ Your feature branch pushed to the remote repository
✅ Your main/master branch unchanged

Solution Verification

Run these commands to verify your work:

# Should show feature/login-tests with an asterisk
git branch

# Should show your commit
git log -1

# Should show your branch exists on remote
git branch -r

Bonus Challenge

  1. Create another test file for logout_test.py
  2. Make a second commit on the same branch
  3. View the difference between your feature branch and main: git diff main..feature/login-tests

KEY TAKEAWAYS

What You Learned

🔑 Feature branches isolate your work - Creating separate branches for each feature or test suite keeps your main branch stable and allows multiple team members to work independently without conflicts.

🔑 Naming conventions matter - Using descriptive branch names like feature/login-tests or test/add-checkout-flow makes it immediately clear what work is being done and helps with organization.

🔑 Commit early and often - Making small, focused commits with clear messages creates a better history and makes it easier to track changes or revert if needed.

🔑 Push to share and backup - Pushing your feature branch to the remote repository backs up your work and enables collaboration through pull requests and code reviews.

🔑 The main branch stays clean - By working on feature branches, your main/master branch remains deployable while development continues in parallel.

When to Apply This

  • Starting any new test development - Always create a feature branch before writing new tests
  • Bug fix tests - Create a branch like bugfix/fix-login-timeout-test
  • Refactoring existing tests - Use refactor/improve-api-tests
  • Team collaboration - Before submitting tests for code review
  • Experimental tests - Try new approaches without affecting the main codebase

NEXT STEPS

What to Practice

  1. Create multiple feature branches - Practice switching between different test features using git checkout
  2. Write meaningful commit messages - Follow the pattern: “Add/Update/Fix [what] for [why]”
  3. Review your changes before committing - Use git diff to see exactly what you’re committing
  4. Delete merged branches - After branches are merged, clean up with git branch -d branch-name

Immediate Next Steps:

  • Creating and reviewing pull requests for your test branches
  • Merging feature branches back into main
  • Resolving merge conflicts in test files
  • Using .gitignore to exclude test reports and artifacts

Intermediate Topics:

  • Git branching strategies (Git Flow, GitHub Flow)
  • Rebasing vs merging feature branches
  • Using tags for test release versions
  • Setting up branch protection rules

Advanced Topics:

  • Automating tests on feature branches with CI/CD
  • Git hooks for running tests before commits
  • Collaborative test development workflows
  • Managing test data across branches

Build a complete test suite over the next week:

  • Day 1-2: Create branches for login/logout tests
  • Day 3-4: Create branches for user registration tests
  • Day 5-6: Create branches for navigation tests
  • Day 7: Merge all branches and review your workflow

🎓 Remember: Feature branches are your safety net. They give you the freedom to experiment, make mistakes, and iterate on your tests without fear of breaking the main codebase. Make branch creation a habit in your testing workflow!