PramodDutta/qaskills/seed-skills/gauge-testing/SKILL.md
Gauge Testing
Test automation with Gauge framework using Markdown specifications, step implementations in Java/Python/JavaScript/Ruby/C#, concepts, data-driven testing, and living documentation.
- Source repository stars
- 195
- Declared platforms
- 3
- Static risk flags
- 1
- Last source update
- 2026-08-04
- Source checked
- 2026-08-04
Decision brief
What it does—and where it fits
You are an expert QA engineer specializing in Gauge, ThoughtWorks' open-source test automation framework. When the user asks you to write, review, debug, or set up Gauge tests, follow these detailed instructions. You understand the Gauge ecosystem deeply including Markdown-based…
Not for
- Avoid implementation details in specs — Specifications should describe behavior, not browser interactions like Click CSS btn-submit.
- Avoid monolithic step files — Split step implementations by domain (auth, shopping, API) for maintainability.
Compatibility matrix
Platform support, with evidence labels
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Declared | Source record | Install path and trigger |
| Claude Code | Declared | Source record | Install path and trigger |
| Cursor | Declared | Source record | Install path and trigger |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
Inspect first. Install second.
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/PramodDutta/qaskills --skill "seed-skills/gauge-testing"Inspect the Agent Skill "Gauge Testing" from https://github.com/PramodDutta/qaskills/blob/c924c5f7fee5fa410f267031061e492eb051757a/seed-skills/gauge-testing/SKILL.md at commit c924c5f7fee5fa410f267031061e492eb051757a. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
What the source asks the agent to do
- 01
Concepts (Reusable Step Groups)
Review the “Concepts (Reusable Step Groups)” section in the pinned source before continuing.
Review and apply the “Concepts (Reusable Step Groups)” source section. - 02
Step Implementations (Java)
Review the “Step Implementations (Java)” section in the pinned source before continuing.
Review and apply the “Step Implementations (Java)” source section. - 03
Step Implementations (Python)
Review the “Step Implementations (Python)” section in the pinned source before continuing.
Review and apply the “Step Implementations (Python)” source section. - 04
Step Implementations (JavaScript)
Review the “Step Implementations (JavaScript)” section in the pinned source before continuing.
Review and apply the “Step Implementations (JavaScript)” source section. - 05
Core Principles
1. Readable Specifications — Write specifications in plain Markdown that anyone on the team can read and understand. Specifications are living documentation, not just tests. 2. Language-Agnostic Specs — Specifications are decoupled from implementation language. The same spec can…
Readable Specifications — Write specifications in plain Markdown that anyone on the team can read and understand. Specifications are living documentation, not just tests.Language-Agnostic Specs — Specifications are decoupled from implementation language. The same spec can be backed by Java, Python, JavaScript, Ruby, or C step implementations.Concept Reusability — Group common step sequences into Concepts (reusable specification fragments) to avoid duplication and maintain DRY test specifications.
Permission review
Static risk signals and limitations
Network access
The documentation includes network, browsing, or remote request actions.
Send POST request to "/api/users" with name <name> and email <email>Network access
The documentation includes network, browsing, or remote request actions.
? System.getenv("BASE_URL") : "http://localhost:3000";Evidence record
Why each signal appears
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 90/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 195 | Source | Repository attention, not individual Skill quality |
| Compatibility | 3 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Provenance and original SKILL.md
- Repository
- PramodDutta/qaskills
- Skill path
- seed-skills/gauge-testing/SKILL.md
- Commit
- c924c5f7fee5fa410f267031061e492eb051757a
- License
- MIT
- Collected
- 2026-08-04
- Default branch
- main
View the original SKILL.md
Gauge Testing
You are an expert QA engineer specializing in Gauge, ThoughtWorks' open-source test automation framework. When the user asks you to write, review, debug, or set up Gauge tests, follow these detailed instructions. You understand the Gauge ecosystem deeply including Markdown-based specifications, multi-language step implementations (Java, Python, JavaScript, Ruby, C#), concepts, data tables, tags, hooks, screenshots, and parallel execution.
Core Principles
- Readable Specifications — Write specifications in plain Markdown that anyone on the team can read and understand. Specifications are living documentation, not just tests.
- Language-Agnostic Specs — Specifications are decoupled from implementation language. The same spec can be backed by Java, Python, JavaScript, Ruby, or C# step implementations.
- Concept Reusability — Group common step sequences into Concepts (reusable specification fragments) to avoid duplication and maintain DRY test specifications.
- Data-Driven Testing — Use Markdown tables and CSV data sources for data-driven scenarios. Parameterize specifications rather than duplicating them.
- Parallel by Design — Gauge supports parallel execution at the specification level. Design tests for isolation from the start.
- Hooks for Lifecycle — Use execution hooks (BeforeSuite, AfterSuite, BeforeSpec, AfterSpec, BeforeScenario, AfterScenario, BeforeStep, AfterStep) for setup and teardown.
- Screenshot on Failure — Gauge automatically captures screenshots on failure. Configure custom screenshot strategies for non-browser tests.
Project Structure
project-root/
├── manifest.json # Gauge project configuration
├── env/
│ ├── default/
│ │ └── default.properties # Default environment variables
│ ├── staging/
│ │ └── staging.properties # Staging environment overrides
│ └── ci/
│ └── ci.properties # CI environment overrides
├── specs/
│ ├── auth/
│ │ ├── login.spec # Login specification
│ │ ├── signup.spec # Signup specification
│ │ └── concepts/
│ │ └── auth.cpt # Auth-related concepts
│ ├── shopping/
│ │ ├── cart.spec
│ │ ├── checkout.spec
│ │ └── concepts/
│ │ └── shopping.cpt
│ └── api/
│ ├── users_api.spec
│ └── orders_api.spec
├── src/test/java/ # Java step implementations
│ ├── steps/
│ │ ├── AuthSteps.java
│ │ ├── ShoppingSteps.java
│ │ └── ApiSteps.java
│ ├── pages/
│ │ ├── BasePage.java
│ │ ├── LoginPage.java
│ │ └── DashboardPage.java
│ └── hooks/
│ └── ExecutionHooks.java
├── reports/
│ └── html-report/
└── pom.xml # Maven configuration (Java)
Detailed Code Examples
Specification File (Markdown)
# User Authentication
Tags: auth, smoke
## Successful Login
Tags: positive, critical
* Navigate to login page
* Enter email "[email protected]"
* Enter password "SecurePass123"
* Click the login button
* Verify user is on the dashboard
* Verify welcome message contains "Welcome"
## Login with Invalid Credentials
Tags: negative
* Navigate to login page
* Enter email "[email protected]"
* Enter password "wrongpassword"
* Click the login button
* Verify error message "Invalid credentials" is displayed
* Verify user is still on the login page
## Login Validation Errors
|email |password |error |
|-------------------|-------------|----------------------|
| |SecurePass123|Email is required |
|[email protected] | |Password is required |
|invalid-email |SecurePass123|Invalid email format |
* Navigate to login page
* Enter email <email>
* Enter password <password>
* Click the login button
* Verify error message <error> is displayed
Concepts (Reusable Step Groups)
# Login as user with email <email> and password <password>
* Navigate to login page
* Enter email <email>
* Enter password <password>
* Click the login button
* Verify user is on the dashboard
# Create a new user with name <name> and email <email>
* Send POST request to "/api/users" with name <name> and email <email>
* Verify response status code is "201"
* Save created user ID
# Add product to cart and verify
* Click "Add to Cart" button for the current product
* Verify cart count increases by "1"
* Verify success notification is displayed
Step Implementations (Java)
// src/test/java/steps/AuthSteps.java
package steps;
import com.thoughtworks.gauge.Step;
import com.thoughtworks.gauge.Table;
import com.thoughtworks.gauge.TableRow;
import com.thoughtworks.gauge.datastore.ScenarioDataStore;
import org.openqa.selenium.WebDriver;
import pages.LoginPage;
import pages.DashboardPage;
import static org.assertj.core.api.Assertions.assertThat;
public class AuthSteps {
private final LoginPage loginPage;
private final DashboardPage dashboardPage;
public AuthSteps() {
WebDriver driver = DriverFactory.getDriver();
this.loginPage = new LoginPage(driver);
this.dashboardPage = new DashboardPage(driver);
}
@Step("Navigate to login page")
public void navigateToLoginPage() {
loginPage.open();
assertThat(loginPage.isLoaded()).isTrue();
}
@Step("Enter email <email>")
public void enterEmail(String email) {
loginPage.enterEmail(email);
}
@Step("Enter password <password>")
public void enterPassword(String password) {
loginPage.enterPassword(password);
}
@Step("Click the login button")
public void clickLoginButton() {
loginPage.clickLogin();
}
@Step("Verify user is on the dashboard")
public void verifyOnDashboard() {
assertThat(dashboardPage.isLoaded())
.as("User should be on the dashboard")
.isTrue();
}
@Step("Verify welcome message contains <text>")
public void verifyWelcomeMessage(String text) {
String message = dashboardPage.getWelcomeMessage();
assertThat(message)
.as("Welcome message should contain '%s'", text)
.contains(text);
}
@Step("Verify error message <message> is displayed")
public void verifyErrorMessage(String message) {
String actual = loginPage.getErrorMessage();
assertThat(actual)
.as("Error message should be '%s'", message)
.isEqualTo(message);
}
@Step("Verify user is still on the login page")
public void verifyStillOnLoginPage() {
assertThat(loginPage.isLoaded())
.as("User should still be on the login page")
.isTrue();
}
}
Step Implementations (Python)
# step_impl/auth_steps.py
from getgauge.python import step, before_scenario, after_scenario, data_store
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from pages.login_page import LoginPage
from pages.dashboard_page import DashboardPage
@before_scenario
def setup_browser(context):
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--window-size=1920,1080")
driver = webdriver.Chrome(options=chrome_options)
data_store.scenario["driver"] = driver
data_store.scenario["login_page"] = LoginPage(driver)
data_store.scenario["dashboard_page"] = DashboardPage(driver)
@after_scenario
def teardown_browser(context):
driver = data_store.scenario.get("driver")
if driver:
driver.quit()
@step("Navigate to login page")
def navigate_to_login():
page = data_store.scenario["login_page"]
page.open()
assert page.is_loaded(), "Login page did not load"
@step("Enter email <email>")
def enter_email(email):
data_store.scenario["login_page"].enter_email(email)
@step("Enter password <password>")
def enter_password(password):
data_store.scenario["login_page"].enter_password(password)
@step("Click the login button")
def click_login():
data_store.scenario["login_page"].click_login()
@step("Verify user is on the dashboard")
def verify_on_dashboard():
page = data_store.scenario["dashboard_page"]
assert page.is_loaded(), "Dashboard did not load"
@step("Verify welcome message contains <text>")
def verify_welcome(text):
page = data_store.scenario["dashboard_page"]
message = page.get_welcome_message()
assert text in message, f"Expected '{text}' in '{message}'"
@step("Verify error message <message> is displayed")
def verify_error(message):
page = data_store.scenario["login_page"]
actual = page.get_error_message()
assert actual == message, f"Expected '{message}', got '{actual}'"
Step Implementations (JavaScript)
// tests/step_implementation.js
const { Step, BeforeSuite, AfterSuite, BeforeScenario, AfterScenario } = require('gauge-ts');
const { Builder, By, until } = require('selenium-webdriver');
const assert = require('assert');
let driver;
BeforeScenario(async () => {
driver = await new Builder().forBrowser('chrome').build();
});
AfterScenario(async () => {
if (driver) await driver.quit();
});
Step('Navigate to login page', async () => {
await driver.get(process.env.BASE_URL + '/login');
await driver.wait(until.elementLocated(By.css('[data-testid="email-input"]')), 10000);
});
Step('Enter email <email>', async (email) => {
const input = await driver.findElement(By.css('[data-testid="email-input"]'));
await input.clear();
await input.sendKeys(email);
});
Step('Enter password <password>', async (password) => {
const input = await driver.findElement(By.css('[data-testid="password-input"]'));
await input.clear();
await input.sendKeys(password);
});
Step('Click the login button', async () => {
await driver.findElement(By.css('[data-testid="login-submit"]')).click();
});
Step('Verify user is on the dashboard', async () => {
await driver.wait(until.urlContains('/dashboard'), 10000);
const url = await driver.getCurrentUrl();
assert(url.includes('/dashboard'), `Expected dashboard URL, got ${url}`);
});
Step('Verify error message <message> is displayed', async (message) => {
const element = await driver.wait(
until.elementLocated(By.css('[data-testid="error-message"]')), 10000
);
const text = await element.getText();
assert.strictEqual(text, message, `Expected '${message}', got '${text}'`);
});
Page Object (Java)
// src/test/java/pages/BasePage.java
package pages;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.time.Duration;
public abstract class BasePage {
protected WebDriver driver;
protected WebDriverWait wait;
protected String baseUrl;
public BasePage(WebDriver driver) {
this.driver = driver;
this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
this.baseUrl = System.getenv("BASE_URL") != null
? System.getenv("BASE_URL") : "http://localhost:3000";
}
protected WebElement findElement(By locator) {
return wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
}
protected void click(By locator) {
wait.until(ExpectedConditions.elementToBeClickable(locator)).click();
}
protected void type(By locator, String text) {
WebElement element = findElement(locator);
element.clear();
element.sendKeys(text);
}
protected String getText(By locator) {
return findElement(locator).getText();
}
protected void waitForUrl(String urlPart) {
wait.until(ExpectedConditions.urlContains(urlPart));
}
public void takeScreenshot(String name) {
TakesScreenshot ts = (TakesScreenshot) driver;
byte[] screenshot = ts.getScreenshotAs(OutputType.BYTES);
Gauge.writeMessage("Screenshot: " + name);
Gauge.captureScreenshot();
}
}
// src/test/java/pages/LoginPage.java
package pages;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class LoginPage extends BasePage {
private static final By EMAIL_INPUT = By.cssSelector("[data-testid='email-input']");
private static final By PASSWORD_INPUT = By.cssSelector("[data-testid='password-input']");
private static final By LOGIN_BUTTON = By.cssSelector("[data-testid='login-submit']");
private static final By ERROR_MESSAGE = By.cssSelector("[data-testid='error-message']");
public LoginPage(WebDriver driver) { super(driver); }
public void open() {
driver.get(baseUrl + "/login");
}
public void enterEmail(String email) { type(EMAIL_INPUT, email); }
public void enterPassword(String password) { type(PASSWORD_INPUT, password); }
public void clickLogin() { click(LOGIN_BUTTON); }
public String getErrorMessage() { return getText(ERROR_MESSAGE); }
public boolean isLoaded() {
try { findElement(EMAIL_INPUT); return true; }
catch (Exception e) { return false; }
}
}
Execution Hooks
// src/test/java/hooks/ExecutionHooks.java
package hooks;
import com.thoughtworks.gauge.*;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
public class ExecutionHooks {
@BeforeSuite
public void beforeSuite() {
System.out.println("Test suite starting...");
}
@AfterSuite
public void afterSuite() {
System.out.println("Test suite completed.");
}
@BeforeScenario
public void beforeScenario(ExecutionContext context) {
ChromeOptions options = new ChromeOptions();
if (System.getenv("CI") != null) {
options.addArguments("--headless", "--no-sandbox", "--disable-dev-shm-usage");
}
options.addArguments("--window-size=1920,1080");
WebDriver driver = new ChromeDriver(options);
DriverFactory.setDriver(driver);
System.out.println("Starting scenario: " + context.getCurrentScenario().getName());
}
@AfterScenario
public void afterScenario(ExecutionContext context) {
if (context.getCurrentScenario().getIsFailing()) {
DriverFactory.getDriver().manage().window().maximize();
Gauge.captureScreenshot();
}
DriverFactory.getDriver().quit();
}
@BeforeStep
public void beforeStep(ExecutionContext context) {
// Log step execution for debugging
}
@AfterStep
public void afterStep(ExecutionContext context) {
if (context.getCurrentStep().getIsFailing()) {
Gauge.captureScreenshot();
}
}
}
Environment Configuration
# env/default/default.properties
base_url = http://localhost:3000
browser = chrome
headless = false
implicit_wait = 10
screenshot_on_failure = true
# env/ci/ci.properties
base_url = http://staging.example.com
browser = chrome
headless = true
implicit_wait = 15
screenshot_on_failure = true
parallel_execution = true
Data-Driven Testing with CSV
# Product Search
Tags: search, data-driven
table: resources/search_data.csv
## Search for products by category
* Navigate to the product catalog
* Search for <query>
* Verify <expected_count> results are displayed
* Verify first result contains <expected_product>
query,expected_count,expected_product
laptop,15,MacBook Pro
headphones,8,Sony WH-1000XM5
keyboard,12,Keychron K8
CI/CD Integration (GitHub Actions)
name: Gauge Tests
on: [push, pull_request]
jobs:
gauge-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Install Gauge
run: |
curl -SsL https://downloads.gauge.org/stable | sh
gauge install java
gauge install html-report
gauge install screenshot
- name: Start application
run: ./start-app.sh &
- name: Run Gauge specs
run: gauge run --tags "smoke" --parallel -n 4 specs/
env:
BASE_URL: http://localhost:3000
CI: true
- uses: actions/upload-artifact@v4
if: always()
with:
name: gauge-reports
path: reports/
Best Practices
- Write specifications in business language — Gauge specs are Markdown, making them natural documentation. Write them so product managers can review and understand.
- Use concepts for reusable sequences — Extract common step patterns into
.cptconcept files to maintain DRY specifications. - Organize specs by feature area — Group related specifications in directories. Use tags for cross-cutting concerns (smoke, regression).
- Use data tables for parameterized scenarios — Inline tables or CSV files make data-driven testing clean and easy to extend.
- Use data stores appropriately — ScenarioDataStore for scenario scope, SpecDataStore for specification scope, SuiteDataStore for global data.
- Implement proper Page Objects — Keep step implementations thin. Business logic and browser interactions belong in page objects.
- Configure environment-specific properties — Use Gauge's env directory to manage configuration for different environments.
- Enable parallel execution — Use
gauge run --parallel -n <threads>for faster execution. Design specs to be independent. - Capture screenshots on failure — Use
Gauge.captureScreenshot()in AfterStep hooks to automatically capture failure evidence. - Generate HTML reports — Use gauge's built-in HTML report plugin for comprehensive test results with screenshots and step details.
Anti-Patterns to Avoid
- Avoid implementation details in specs — Specifications should describe behavior, not browser interactions like
Click CSS #btn-submit. - Avoid monolithic step files — Split step implementations by domain (auth, shopping, API) for maintainability.
- Avoid coupling between scenarios — Each scenario must be independently executable. Never depend on previous scenario outcomes.
- Avoid hardcoded data — Use environment properties and data tables. Hardcoded URLs and credentials break portability.
- Avoid long scenarios — Keep scenarios focused on one behavior. If a scenario exceeds 10 steps, extract concepts or decompose.
- Avoid ignoring Gauge's data stores — Use ScenarioDataStore instead of global variables. Data stores are properly scoped and thread-safe.
- Avoid skipping hooks — Always implement AfterScenario to clean up resources (browsers, database records, temp files).
- Avoid duplicate steps — If multiple step files define the same step, Gauge raises ambiguity errors. Centralize shared steps.
- Avoid testing external services directly — Mock external APIs. Gauge tests should verify your application's behavior, not third-party services.
- Avoid missing tags — Tag every specification and scenario. Tags enable selective execution, reporting, and hook targeting.
Alternatives
Compare before choosing
alirezarezvani/claude-skills
research-ops-skills
Use when planning, funding, scoping, or synthesizing enterprise research across workstreams — clinical study design, R&D program finance, market sizing/surveys, or product/user research. Triggers on "design this clinical study", "what sample size", "R&D budget", "burn rate", "capitalize or expense", "TAM SAM SOM", "market sizing", "survey design", "segment the market", "plan user interviews", "usability test", "synthesize research insights". Forks context to route to one of four Research-Operati
PramodDutta/qaskills
Robot Framework Testing
Expert-level Robot Framework testing skill covering keyword-driven syntax, SeleniumLibrary, RequestsLibrary, custom Python keywords, data-driven testing, resource files, and parallel execution with Pabot.
PramodDutta/qaskills
API Test Suite Generator
Automatically generate comprehensive API test suites from OpenAPI specifications covering CRUD operations, error handling, authentication, pagination, and edge cases
PramodDutta/qaskills
Cursor AI Testing Patterns
Effective test automation patterns with Cursor AI IDE including Composer for test suite generation, Cmd+K for inline test edits, Chat for test debugging, codebase-aware test generation, and rules configuration for testing conventions.