Source profileQuality 90/100

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…

Best for

    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

    PlatformStatusEvidenceWhat to check
    CodexDeclaredSource recordInstall path and trigger
    Claude CodeDeclaredSource recordInstall path and trigger
    CursorDeclaredSource recordInstall path and trigger
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    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.

    Source-detected install commandSource
    npx skills add https://github.com/PramodDutta/qaskills --skill "seed-skills/gauge-testing"
    Safe inspection promptEditorial

    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

    1. 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.
    2. 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.
    3. 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.
    4. 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.
    5. 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

    medium · line 113

    The documentation includes network, browsing, or remote request actions.

    Send POST request to "/api/users" with name <name> and email <email>

    Network access

    medium · line 349

    The documentation includes network, browsing, or remote request actions.

    ? System.getenv("BASE_URL") : "http://localhost:3000";

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score90/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars195SourceRepository attention, not individual Skill quality
    Compatibility3 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated 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

    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 be backed by Java, Python, JavaScript, Ruby, or C# step implementations.
    3. Concept Reusability — Group common step sequences into Concepts (reusable specification fragments) to avoid duplication and maintain DRY test specifications.
    4. Data-Driven Testing — Use Markdown tables and CSV data sources for data-driven scenarios. Parameterize specifications rather than duplicating them.
    5. Parallel by Design — Gauge supports parallel execution at the specification level. Design tests for isolation from the start.
    6. Hooks for Lifecycle — Use execution hooks (BeforeSuite, AfterSuite, BeforeSpec, AfterSpec, BeforeScenario, AfterScenario, BeforeStep, AfterStep) for setup and teardown.
    7. 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

    1. Write specifications in business language — Gauge specs are Markdown, making them natural documentation. Write them so product managers can review and understand.
    2. Use concepts for reusable sequences — Extract common step patterns into .cpt concept files to maintain DRY specifications.
    3. Organize specs by feature area — Group related specifications in directories. Use tags for cross-cutting concerns (smoke, regression).
    4. Use data tables for parameterized scenarios — Inline tables or CSV files make data-driven testing clean and easy to extend.
    5. Use data stores appropriately — ScenarioDataStore for scenario scope, SpecDataStore for specification scope, SuiteDataStore for global data.
    6. Implement proper Page Objects — Keep step implementations thin. Business logic and browser interactions belong in page objects.
    7. Configure environment-specific properties — Use Gauge's env directory to manage configuration for different environments.
    8. Enable parallel execution — Use gauge run --parallel -n <threads> for faster execution. Design specs to be independent.
    9. Capture screenshots on failure — Use Gauge.captureScreenshot() in AfterStep hooks to automatically capture failure evidence.
    10. Generate HTML reports — Use gauge's built-in HTML report plugin for comprehensive test results with screenshots and step details.

    Anti-Patterns to Avoid

    1. Avoid implementation details in specs — Specifications should describe behavior, not browser interactions like Click CSS #btn-submit.
    2. Avoid monolithic step files — Split step implementations by domain (auth, shopping, API) for maintainability.
    3. Avoid coupling between scenarios — Each scenario must be independently executable. Never depend on previous scenario outcomes.
    4. Avoid hardcoded data — Use environment properties and data tables. Hardcoded URLs and credentials break portability.
    5. Avoid long scenarios — Keep scenarios focused on one behavior. If a scenario exceeds 10 steps, extract concepts or decompose.
    6. Avoid ignoring Gauge's data stores — Use ScenarioDataStore instead of global variables. Data stores are properly scoped and thread-safe.
    7. Avoid skipping hooks — Always implement AfterScenario to clean up resources (browsers, database records, temp files).
    8. Avoid duplicate steps — If multiple step files define the same step, Gauge raises ambiguity errors. Centralize shared steps.
    9. Avoid testing external services directly — Mock external APIs. Gauge tests should verify your application's behavior, not third-party services.
    10. Avoid missing tags — Tag every specification and scenario. Tags enable selective execution, reporting, and hook targeting.

    Alternatives

    Compare before choosing