Introduction to Gauge Framework
Gauge is a modern, open-source test automation framework from ThoughtWorks that brings a fresh perspective to behavior-driven development (BDD). Unlike traditional BDD (as discussed in BDD: From Requirements to Automation) tools that use domain-specific languages like Gherkin, Gauge uses Markdown for writing specifications, making it more accessible and familiar to technical and non-technical team members alike.
This comprehensive guide explores Gauge’s unique approach to BDD (as discussed in Cucumber BDD Automation: Complete Guide to Behavior-Driven Development Testing), covering Markdown-based specifications, language-independent architecture, parallel execution capabilities, plugin ecosystem, and detailed comparison with Cucumber.
Markdown Specifications: A Natural Approach
Gauge specifications use Markdown format, eliminating the need to learn new syntax while providing rich formatting capabilities.
Basic Gauge Specification
# User Authentication
## Successful login with valid credentials
* Navigate to login page
* Enter username "john.doe@example.com"
* Enter password "SecurePass123"
* Click login button
* Verify user is redirected to dashboard
* Verify welcome message "Welcome, John"
## Failed login with invalid credentials
* Navigate to login page
* Enter username "john.doe@example.com"
* Enter password "wrongpassword"
* Click login button
* Verify error message "Invalid credentials"
* Verify user remains on login page
Specification Structure
Element | Markdown Syntax | Purpose |
---|---|---|
Specification | # Title | Top-level container |
Scenario | ## Description | Individual test case |
Step | * Action | Test step |
Tag | tags: smoke, critical | Categorization |
Comment | // Comment | Documentation |
Concept | Reusable step group | Step abstraction |
Advanced Specification Features
# E-Commerce Shopping Cart
tags: shopping, critical
## Context Setup
* Login as "standard_user"
* Navigate to products page
## Add product to cart
* Add product "Laptop Computer" to cart
* Verify cart count is "1"
* Verify cart total is "$999.99"
## Add multiple quantities
* Add "3" units of product "USB Cable" to cart
* Verify cart count is "3"
* Verify cart total is "$29.97"
## Remove product from cart
* Add product "Wireless Mouse" to cart
* Remove product "Wireless Mouse" from cart
* Verify cart is empty
* Verify cart count is "0"
Data-Driven Testing with Tables
# Login Validation
tags: validation, parametrized
## Validate login with different credentials
|username|password|expected_result|
|--------|--------|---------------|
|valid@example.com|ValidPass123|Welcome to Dashboard|
|invalid@example.com|anything|User not found|
|valid@example.com|wrongpass|Invalid credentials|
|@invalid.com|ValidPass123|Invalid email format|
|valid@example.com|123|Password too short|
* Verify login with credentials <username>, <password> shows <expected_result>
Language Independence: True Polyglot Testing
Gauge’s architecture allows implementing step definitions in any programming language, providing unprecedented flexibility.
Java Implementation
// src/test/java/StepImplementation.java
package com.example;
import com.thoughtworks.gauge.Step;
import com.thoughtworks.gauge.Table;
import com.thoughtworks.gauge.TableRow;
import pages.LoginPage;
import pages.DashboardPage;
public class StepImplementation {
private LoginPage loginPage;
private DashboardPage dashboardPage;
@Step("Navigate to login page")
public void navigateToLogin() {
loginPage = new LoginPage();
loginPage.open();
}
@Step("Enter username <username>")
public void enterUsername(String username) {
loginPage.enterUsername(username);
}
@Step("Enter password <password>")
public void enterPassword(String password) {
loginPage.enterPassword(password);
}
@Step("Click login button")
public void clickLogin() {
dashboardPage = loginPage.clickLogin();
}
@Step("Verify user is redirected to dashboard")
public void verifyDashboard() {
assertTrue(dashboardPage.isDisplayed());
}
@Step("Verify login with credentials <username>, <password> shows <result>")
public void verifyLoginWithCredentials(String username, String password, String result) {
navigateToLogin();
enterUsername(username);
enterPassword(password);
clickLogin();
assertEquals(result, loginPage.getMessageOrDashboardText());
}
}
JavaScript/TypeScript Implementation
// tests/step_implementations/authentication.ts
import { Step, Table } from "gauge-ts";
import { LoginPage } from "../pages/LoginPage";
import { DashboardPage } from "../pages/DashboardPage";
import { expect } from "@playwright/test";
let loginPage: LoginPage;
let dashboardPage: DashboardPage;
Step("Navigate to login page", async function() {
loginPage = new LoginPage(gauge.page);
await loginPage.navigate();
});
Step("Enter username <username>", async function(username: string) {
await loginPage.enterUsername(username);
});
Step("Enter password <password>", async function(password: string) {
await loginPage.enterPassword(password);
});
Step("Click login button", async function() {
await loginPage.clickLogin();
dashboardPage = new DashboardPage(gauge.page);
});
Step("Verify user is redirected to dashboard", async function() {
await expect(dashboardPage.container).toBeVisible();
});
Step("Verify welcome message <message>", async function(message: string) {
const actual = await dashboardPage.getWelcomeMessage();
expect(actual).toBe(message);
});
Step("Verify login with credentials <username>, <password> shows <result>",
async function(username: string, password: string, expectedResult: string) {
await loginPage.navigate();
await loginPage.enterUsername(username);
await loginPage.enterPassword(password);
await loginPage.clickLogin();
const actualResult = await loginPage.getMessageOrDashboardText();
expect(actualResult).toContain(expectedResult);
});
Python Implementation
# step_impl/authentication_steps.py
from getgauge.python import step, Table
from pages.login_page import LoginPage
from pages.dashboard_page import DashboardPage
login_page = None
dashboard_page = None
@step("Navigate to login page")
def navigate_to_login():
global login_page
login_page = LoginPage()
login_page.navigate()
@step("Enter username <username>")
def enter_username(username):
login_page.enter_username(username)
@step("Enter password <password>")
def enter_password(password):
login_page.enter_password(password)
@step("Click login button")
def click_login():
global dashboard_page
login_page.click_login()
dashboard_page = DashboardPage()
@step("Verify user is redirected to dashboard")
def verify_dashboard_redirect():
assert dashboard_page.is_displayed(), "Dashboard not displayed"
@step("Verify welcome message <message>")
def verify_welcome_message(message):
actual = dashboard_page.get_welcome_message()
assert actual == message, f"Expected '{message}', got '{actual}'"
@step("Verify login with credentials <username>, <password> shows <result>")
def verify_login_credentials(username, password, expected_result):
navigate_to_login()
enter_username(username)
enter_password(password)
click_login()
actual_result = login_page.get_message_or_dashboard_text()
assert expected_result in actual_result
Parallel Execution: Built-in Performance
Gauge provides native parallel execution capabilities without external plugins.
Parallel Execution Configuration
# env/default/default.properties
# Number of parallel streams
gauge_parallel_streams = 4
# Execution strategy: lazy (default) or eager
gauge_execution_type = lazy
# Enable/disable screenshots on failure
screenshot_on_failure = true
# Report configuration
gauge_reports_dir = reports
overwrite_reports = true
# Browser configuration for parallel execution
BROWSER = chrome
HEADLESS = true
Running Tests in Parallel
# Run with 4 parallel streams
gauge run specs --parallel --max-workers=4
# Run specific tags in parallel
gauge run specs --tags "smoke & critical" --parallel
# Parallel execution with custom streams
gauge run specs --parallel --max-workers=8 --strategy=eager
# Parallel with custom environment
gauge run specs --env qa --parallel --max-workers=4
Parallel Execution Performance Comparison
Test Suite Size | Sequential | 2 Workers | 4 Workers | 8 Workers |
---|---|---|---|---|
100 scenarios | 450s | 235s (48% faster) | 125s (72% faster) | 70s (84% faster) |
500 scenarios | 2100s | 1100s (48% faster) | 580s (72% faster) | 320s (85% faster) |
1000 scenarios | 4200s | 2200s (48% faster) | 1150s (73% faster) | 630s (85% faster) |
Concepts: Reusable Step Groups
Concepts allow grouping related steps into reusable components, promoting DRY principles.
Defining Concepts
<!-- concepts/login_concepts.cpt -->
# Login as user <username> with password <password>
* Navigate to login page
* Enter username <username>
* Enter password <password>
* Click login button
# Login as admin
* Login as user "admin@example.com" with password "admin123"
* Verify admin dashboard is displayed
# Login as standard user
* Login as user "user@example.com" with password "user123"
* Verify user dashboard is displayed
# Add product <product_name> to cart
* Search for product <product_name>
* Click on product <product_name>
* Click add to cart button
* Verify product added confirmation
# Complete checkout with <payment_method>
* Navigate to cart
* Click checkout button
* Fill shipping information
* Select payment method <payment_method>
* Confirm order
* Verify order confirmation
Using Concepts in Specifications
# E-Commerce Complete Flow
tags: integration, e2e
## Successful purchase flow
* Login as standard user
* Add product "Laptop Pro" to cart
* Add product "Wireless Mouse" to cart
* Complete checkout with "Credit Card"
* Verify order total is "$1,029.98"
* Verify order confirmation email sent
## Guest checkout
* Add product "USB Cable" to cart
* Complete checkout with "PayPal"
* Verify order confirmation page
Hooks and Execution Lifecycle
Gauge provides comprehensive hooks for test lifecycle management.
Java Hooks Implementation
// src/test/java/Hooks.java
package com.example;
import com.thoughtworks.gauge.*;
import org.openqa.selenium.WebDriver;
import utils.DriverFactory;
import utils.DatabaseUtils;
public class Hooks {
private WebDriver driver;
@BeforeSuite
public void beforeSuite(ExecutionContext context) {
System.out.println("Starting test suite: " +
context.getCurrentSpecification().getName());
DatabaseUtils.initializeTestDatabase();
}
@BeforeSpec
public void beforeSpec(ExecutionContext context) {
System.out.println("Starting spec: " +
context.getCurrentSpecification().getName());
}
@BeforeScenario
public void beforeScenario(ExecutionContext context) {
System.out.println("Starting scenario: " +
context.getCurrentScenario().getName());
driver = DriverFactory.getDriver();
Gauge.writeMessage("Browser launched");
}
@BeforeStep
public void beforeStep(ExecutionContext context) {
// Can be used for logging or screenshots
}
@AfterStep
public void afterStep(ExecutionContext context) {
if (context.getCurrentStep().getIsFailing()) {
byte[] screenshot = DriverFactory.takeScreenshot(driver);
Gauge.writeMessage("Step failed, screenshot attached");
}
}
@AfterScenario
public void afterScenario(ExecutionContext context) {
if (context.getCurrentScenario().getIsFailing()) {
byte[] screenshot = DriverFactory.takeScreenshot(driver);
Gauge.captureScreenshot();
}
driver.quit();
}
@AfterSpec
public void afterSpec(ExecutionContext context) {
System.out.println("Completed spec: " +
context.getCurrentSpecification().getName());
}
@AfterSuite
public void afterSuite(ExecutionContext context) {
System.out.println("Test suite completed");
DatabaseUtils.cleanupTestDatabase();
}
}
Gauge vs Cucumber: Comprehensive Comparison
Feature Comparison Table
Feature | Gauge | Cucumber |
---|---|---|
Specification Format | Markdown | Gherkin (custom DSL) |
Learning Curve | Low (familiar Markdown) | Medium (new syntax) |
Language Support | Java, JavaScript, Python, Ruby, C#, Go | Java, JavaScript, Ruby, many more |
Parallel Execution | Built-in native support | Requires plugins (cucumber-jvm-parallel) |
IDE Support | VS Code, IntelliJ IDEA plugins | Excellent (IntelliJ, Eclipse, VS Code) |
Concepts/Reusability | Built-in concept files | Step definition reuse only |
Data Tables | Native Markdown tables | Gherkin tables |
Reporting | HTML, XML, JSON reports | Multiple plugin options |
Community Size | Growing (ThoughtWorks backed) | Large, established |
Documentation | Excellent | Excellent |
Syntax Comparison
Gauge Specification:
# User Login
tags: authentication
## Successful login
* Navigate to login page
* Login as user "john@example.com" with password "pass123"
* Verify dashboard is displayed
Cucumber Feature:
@authentication
Feature: User Login
Scenario: Successful login
Given I navigate to login page
When I login as user "john@example.com" with password "pass123"
Then I should see the dashboard
When to Choose Gauge
Choose Gauge when:
- Team prefers Markdown over custom DSL
- Need built-in parallel execution without plugins
- Want language-independent architecture from start
- Concepts and reusable step groups are priority
- Working with teams familiar with Markdown
- Need lightweight, modern BDD tool
Choose Cucumber when:
- Large existing Cucumber infrastructure
- Need extensive plugin ecosystem
- Team already familiar with Gherkin
- Require broad language support
- Want established community and resources
Gauge Plugin Ecosystem
# Install essential plugins
gauge install java
gauge install javascript
gauge install python
gauge install html-report
gauge install xml-report
gauge install json-report
gauge install screenshot
gauge install spectacle # Beautiful HTML reports
# Install IDE plugins
# VS Code: Search "Gauge" in extensions
# IntelliJ IDEA: File -> Settings -> Plugins -> Gauge
# List installed plugins
gauge list
# Update plugins
gauge update --all
Practical Use Case: E-Commerce Testing
# Complete E-Commerce Purchase Flow
tags: critical, integration, e2e
## Context: Product catalog setup
* Initialize database with test products
* Ensure inventory stock levels are sufficient
## Guest user completes purchase
* Navigate to home page
* Search for product "Laptop Pro 15"
* Add product to cart with quantity "1"
* Proceed to checkout as guest
* Fill guest checkout information
|field|value|
|-----|-----|
|email|guest@example.com|
|firstName|John|
|lastName|Doe|
|address|123 Main St|
|city|San Francisco|
|state|CA|
|zip|94105|
|country|USA|
* Select shipping method "Standard"
* Enter payment details
|cardNumber|expiry|cvv|name|
|----------|------|---|-----|
|4532123456789010|12/25|123|John Doe|
* Submit order
* Verify order confirmation number is generated
* Verify order confirmation email sent to "guest@example.com"
* Verify inventory decreased for "Laptop Pro 15"
## Registered user with saved details
* Login as standard user
* Search for product "Wireless Mouse"
* Add product to cart with quantity "2"
* Proceed to checkout
* Select saved shipping address "Home"
* Select saved payment method "Visa ending 9010"
* Apply coupon code "SAVE10"
* Verify discount applied is "10%"
* Submit order
* Verify order total is "$53.99"
* Verify loyalty points earned "54"
Best Practices for Gauge
1. Specification Organization
specs/
├── api/
│ ├── user_management.spec
│ └── product_catalog.spec
├── ui/
│ ├── authentication.spec
│ ├── shopping_cart.spec
│ └── checkout.spec
├── integration/
│ └── complete_purchase_flow.spec
└── concepts/
├── login_concepts.cpt
├── cart_concepts.cpt
└── checkout_concepts.cpt
2. Effective Step Writing
<!-- Good: Declarative, business-focused -->
* Login as admin
* Add product to cart
* Complete checkout
<!-- Bad: Imperative, UI-focused -->
* Click on login link
* Type "admin" in username field
* Type "pass" in password field
* Click submit button
3. Concept Usage
<!-- Reusable concept -->
# Purchase product <name> as <user_type>
* Login as <user_type>
* Search and add <name> to cart
* Complete checkout with default payment
* Verify order confirmation
<!-- Usage in spec -->
* Purchase product "Laptop" as "premium_user"
* Purchase product "Mouse" as "standard_user"
Conclusion
Gauge represents a modern evolution in BDD testing, offering a refreshing alternative to traditional frameworks. Its use of Markdown specifications eliminates the learning curve of custom DSLs, while its language-independent architecture and built-in parallel execution provide flexibility and performance.
Key advantages of Gauge:
- Accessibility: Markdown format is familiar and easy to learn
- Flexibility: True language independence allows mixing technologies
- Performance: Native parallel execution without plugins
- Reusability: Concepts provide powerful abstraction mechanism
- Modern: Built with current best practices and tooling
Whether you’re starting a new project or looking for a Cucumber (as discussed in Serenity BDD Integration: Living Documentation and Advanced Test Reporting) alternative, Gauge deserves serious consideration. Its thoughtful design, active development by ThoughtWorks, and growing community make it a compelling choice for modern test automation.
For teams valuing simplicity, performance, and language flexibility, Gauge offers a powerful BDD solution that bridges business requirements and automated testing without unnecessary complexity.