Claude Code QA
PramodDutta/qaskills
The complete QA skill for Claude Code — turn Claude into an expert QA engineer that picks the right test type, writes reliable Playwright, Cypress, and pytest tests, eliminates flaky tests, enforces…
E2E testing conventions for Protocol Designer and Labware Library using Playwright + pytest in e2e-testing/.
$ npx skills add Opentrons/opentrons --skill e2e-testing -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Opentrons/opentrons e2e-testing --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/Opentrons/opentrons.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.cursor/skills/e2e-testing .claude/skills/e2e-testing && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "e2e-testing" agent skill from https://github.com/Opentrons/opentrons/tree/edge/.cursor/skills/e2e-testing into .claude/skills/e2e-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "e2e-testing", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/Opentrons/opentrons/tree/edge/.cursor/skills/e2e-testingType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add Opentrons/opentrons --skill e2e-testing -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Opentrons/opentrons e2e-testing --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Opentrons/opentrons.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.cursor/skills/e2e-testing .agents/skills/e2e-testing && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "e2e-testing" agent skill from https://github.com/Opentrons/opentrons/tree/edge/.cursor/skills/e2e-testing into .agents/skills/e2e-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "e2e-testing", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Opentrons/opentrons --skill e2e-testing -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Opentrons/opentrons e2e-testing --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Opentrons/opentrons.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.cursor/skills/e2e-testing .cursor/skills/e2e-testing && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "e2e-testing" agent skill from https://github.com/Opentrons/opentrons/tree/edge/.cursor/skills/e2e-testing into .cursor/skills/e2e-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "e2e-testing", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/Opentrons/opentrons.git --path .cursor/skills/e2e-testing--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add Opentrons/opentrons --skill e2e-testing -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Opentrons/opentrons e2e-testing --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Opentrons/opentrons.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.cursor/skills/e2e-testing .gemini/skills/e2e-testing && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "e2e-testing" agent skill from https://github.com/Opentrons/opentrons/tree/edge/.cursor/skills/e2e-testing into .gemini/skills/e2e-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "e2e-testing", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install Opentrons/opentrons e2e-testingInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add Opentrons/opentrons --skill e2e-testing -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Opentrons/opentrons.git skills-src && mkdir -p .github/skills && cp -r skills-src/.cursor/skills/e2e-testing .github/skills/e2e-testing && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "e2e-testing" agent skill from https://github.com/Opentrons/opentrons/tree/edge/.cursor/skills/e2e-testing into .github/skills/e2e-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "e2e-testing", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Opentrons/opentrons --skill e2e-testing -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Opentrons/opentrons e2e-testing --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Opentrons/opentrons.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.cursor/skills/e2e-testing .opencode/skills/e2e-testing && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "e2e-testing" agent skill from https://github.com/Opentrons/opentrons/tree/edge/.cursor/skills/e2e-testing into .opencode/skills/e2e-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "e2e-testing", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
e2e-testingE2E testing conventions for Protocol Designer and Labware Library using Playwright + pytest in e2e-testing/.
E2E Testing is an agent skill from Opentrons/opentrons. E2E testing conventions for Protocol Designer and Labware Library using Playwright + pytest in e2e-testing/. Use when writing, running, or modifying end-to-end tests, page objects, or Playwright tests.
Its SKILL.md is about 3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Testing & QA, covering End-to-end testing, Unit testing and Browser testing. It works with Playwright and pytest. The repository describes itself as: Software for writing protocols and running them on the Opentrons Flex and Opentrons OT-2. The licence is Apache-2.0.
4 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit a14fef9. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
makenodeuvFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
staging.designer.opentrons.comstaging.labware.opentrons.comdesigner.opentrons.comlabware.opentrons.comFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
APPLITOOLS_API_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
E2E Testing loads about 3k tokens when it runs. Until then it costs about 53 tokens; SKILL.md has 781 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
- `python-dotenv` loads `.env`. Set `APPLITOOLS_API_KEY` to enableAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from Opentrons/opentrons at commit a14fef9, republished under its Apache-2.0 licence (© Opentrons). 781 words, ~2,964 tokens.
.claude/skills/e2e-testing/SKILL.md (or your agent's skills folder).The e2e-testing directory contains end-to-end tests for Protocol Designer (PD) and Labware Library (LL) using:
uv.lock)automation/base_page.py — Shared BasePage class inherited by all page objectsautomation/pd_pages/ — PD page objects (import from automation.pd_pages)automation/ll_pages/ — LL page objects (import from automation.ll_pages)tests/pd/ — PD E2E tests (marked @pytest.mark.pdE2E)tests/ll/ — LL E2E tests (marked @pytest.mark.llE2E)fixtures/ — Protocol JSON files, labware definitions, and test dataALWAYS use Page Object Model and/or Screenplay Pattern when writing or modifying tests.
automation/base_page.py)BasePage provides: click_button, click_test_id, fill_input, wait_for_visible, dismiss_release_notes_toast, highlight_element, goto. Exposes self.is_sandbox (True when TEST_ENV=sandbox). All page objects inherit from it.
automation/pd_pages/)LandingPage, CreateProtocolWizard, PipetteModal, ModuleConfigPage, DeckConfigPage, ProtocolEditorPage, TransferPage, MixStepForm, ThermocyclerStepPage, ThermocyclerProfileModal, TemperatureStepPage, HeaterShakerStepPage, PlateReaderPage, FlexStackerPage, SettingsPage, Timeline.
automation/ll_pages/)DesktopNavigation, LabwareCreator.
tests/pd/ and tests/ll/)test_<feature>_<scenario>@pytest.mark.pdE2E, LL tests with @pytest.mark.llE2E@pytest.mark.slow for tests taking >10 secondsdef test_name(page: Page, pd_base_url: str) -> None:"""Module for <page name> interactions."""
from playwright.sync_api import Page
from automation.base_page import BasePage
class MyPage(BasePage):
"""Page object for <page name>."""
def __init__(self, page: Page) -> None:
super().__init__(page)
def click_submit_button(self) -> None:
"""Click the submit button."""
self.click_button("Submit")
def fill_protocol_name(self, name: str) -> None:
"""Fill in the protocol name field."""
self.fill_input("protocolName", name)import pytest
from playwright.sync_api import Page
from automation.pd_pages import LandingPage, MyPage
@pytest.mark.pdE2E
def test_my_feature(page: Page, pd_base_url: str) -> None:
"""Test description here."""
landing = LandingPage(page)
landing.wait_for_page_load()
my_page = MyPage(page)
my_page.fill_protocol_name("Test Protocol")
my_page.click_submit_button()import pytest
from playwright.sync_api import Page
from automation.ll_pages import DesktopNavigation
@pytest.mark.llE2E
def test_nav_loads(page: Page, ll_base_url: str) -> None:
"""Verify navigation renders."""
page.goto(f"{ll_base_url}/")
nav = DesktopNavigation(page)
nav.wait_for_loaded()Tests run against different environments via TEST_ENV:
https://staging.designer.opentrons.com / LL → https://staging.labware.opentrons.comhttps://designer.opentrons.com / LL → https://labware.opentrons.com| Fixture | Scope | Purpose |
|---|---|---|
pd_base_url | session | Resolves PD URL; starts local preview server when TEST_ENV=local |
ll_base_url | session | Resolves LL URL; starts local preview server when TEST_ENV=local |
page | function | Creates a Playwright page, navigates to the correct app URL based on test markers, saves video |
browser_context_args | session | Viewport 1280x720, video recording |
browser_type_launch_args | session | Headless/headed, slow_mo |
eyes | function | Applitools Eyes session (or None) |
eyes_singleton | session | Shared Applitools Eyes instance |
| Variable | Default | Notes |
|---|---|---|
TEST_ENV | local | local, staging, prod, sandbox |
HEADLESS | (unset) | true / false; overrides default |
SKIP_SERVER_START | false | Skip automatic server build+serve |
PD_SERVER_URL | auto | Override PD URL |
LL_SERVER_URL | auto | Override LL URL |
LL_SERVER_PORT | 4176 | Preferred port for LL local server |
APPLITOOLS_API_KEY | (unset) | Enable Applitools visual checks |
ALWAYS run before committing:
make format # Auto-format (ruff format + ruff check --fix)
make typecheck # Run mypy
make check # lint + typecheck combined
make prep # format + typecheckRunning PD tests:
make test-pd-local # Headless, chromium
make test-pd-local-headed # Headed, 250ms slow-mo
make test-pd-local PYTEST_ARGS="-k test_name" # Run one test
make test-pd-staging # Against staging
make test-pd-prod # Against prod
make test-pd-debug # Headed, 1000ms slow-mo, verboseRunning LL tests:
make test-ll-local # Headless, chromium
make test-ll-local-headed # Headed
make test-ll-staging # Against staging
make test-ll-prod # Against prodOther targets:
make test-unit # Unit tests only
make troubleshoot # Re-run last failures in headed mode
make codegen # Playwright Inspector/recorder (default localhost:4173)
make codegen URL=<url> # Record against custom URLAll functions must have type annotations:
# Good
def my_function(page: Page, name: str) -> None:
"""Docstring here."""
pass
# Bad — Missing type annotations
def my_function(page, name):
passNote: mypy is strict for automation/ but relaxed (disallow_untyped_defs = false) for tests/.
Import page objects from the package, not from internal modules:
# Good
from automation.pd_pages import LandingPage
from automation.ll_pages import LabwareCreator
from automation.base_page import BasePage
# Bad
from automation.pd_pages.landing_page import LandingPageALWAYS add docstrings to modules (top of file), classes, and public methods.
get_by_role() — Semantic HTML rolesget_by_test_id() — Test IDsget_by_text() — Visible textget_by_label() — Form labelsAvoid CSS selectors (brittle) and XPath (hard to maintain).
ALWAYS wait before interacting:
# Good — Using BasePage helper
self.wait_for_visible(element, timeout=5000)
# Good — Using Playwright expect
from playwright.sync_api import expect
expect(element).to_be_visible()
element.click()
# Bad — No wait
self.page.get_by_role("button", name="Submit").click()Every PD test must have @pytest.mark.pdE2E. Every LL test must have @pytest.mark.llE2E. A test cannot have both markers.
eyes pytest fixture (exposed via pytest_plugins = ["eyes"] in conftest.py)python-dotenv loads .env. Set APPLITOOLS_API_KEY to enableeyes yields None (no visual snapshots)from eyes import Eyes
def test_my_feature(page: Page, pd_base_url: str, eyes: Eyes | None) -> None:
# ... navigate ...
if eyes is None:
return
eyes.check("After navigation")
eyes.check_element("Timeline", page.get_by_test_id("TimelineToolbox_scrollContainer"))automation/pd_pages/tests/pd/ using page objects, add @pytest.mark.pdE2Emake test-pd-local PYTEST_ARGS="-k test_name"make checkautomation/ll_pages/tests/ll/ using page objects, add @pytest.mark.llE2Emake test-ll-local PYTEST_ARGS="-k test_name"make checkdef navigate_and_configure(self) -> "NextPage":
"""Navigate to next page and return its page object."""
self.click_button("Next")
from .next_page import NextPage
return NextPage(self.page).github/workflows/pd-e2e-test.yaml — PD E2E tests.github/workflows/ll-e2e-test.yaml — LL E2E tests.github/workflows/e2e-test-checks.yaml — Lint + typechecknode --version (should be >= 22.22.0)cd ../protocol-designer && make build or cd ../labware-library && make buildNODE_OPTIONS=--max-old-space-size=8192pkill -9 nodemake setupuv run python -c "from automation.base_page import BasePage; print('OK')"Default: 300 seconds per test (set in pytest.ini). Per-test override: @pytest.mark.timeout(600). Use make test-pd-debug or make troubleshoot for step-by-step debugging.
make checktime.sleep() — use Playwright's waiting mechanisms@pytest.mark.pdE2E and @pytest.mark.llE2EBasePage from automation.pd_pages.base_page — use automation.base_page© Opentrons, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .cursor/skills/e2e-testing of Opentrons/opentrons.
Open the folder on GitHubat commit a14fef9
E2E Testing next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| E2E Testing this skillOpentrons/opentrons | 521 | — | ~3k | Automated safety check: Notes | Apache-2.0 | |
| Claude Code QAPramodDutta/qaskills | 232 | — | ~2.3k | Automated safety check: Pass | MIT | |
| E2E Agent Browserjh941213/my-cc-harness | 126 | — | ~3.1k | Automated safety check: Notes | None | |
| Python Testingmacalbert/envilder | 138 | — | ~3.1k | Automated safety check: Pass | MIT | |
| Control UI E2Eopenclaw/openclaw | 392k | — | ~2.9k | Automated safety check: Pass | MIT | |
| VerifyGnathonic/mokuro-reader | 209 | — | ~724 | Automated safety check: Pass | GPL-3.0 |
PramodDutta/qaskills
The complete QA skill for Claude Code — turn Claude into an expert QA engineer that picks the right test type, writes reliable Playwright, Cypress, and pytest tests, eliminates flaky tests, enforces…
jh941213/my-cc-harness
E2E test automation using agent-browser CLI. An agent skill from jh941213/my-cc-harness.
macalbert/envilder
Mandatory testing conventions including AAA pattern, test naming, assertions, and mocks.
openclaw/openclaw
A skill your agent uses when designing, testing, fixing, or extending the OpenClaw Control UI GUI, including UI stress-test galleries with feedback inputs, Vitest + Playwright end-to-end checks…
Gnathonic/mokuro-reader
Verify reader features end-to-end by importing a synthetic volume through the real upload modal and driving the reader with Playwright.
spences10/sveltest
Fix and create Svelte 5 tests with vitest-browser-svelte and Playwright.
Opentrons/opentrons
Conventions for the opentrons-ai-client React/TypeScript frontend — project structure, API integration, state management (Jotai), feature flags, types, and testing.
Opentrons/opentrons
Conventions for the opentrons-ai-server FastAPI service — project structure, uv dependency management, settings, testing, Docker, and deployment.
Opentrons/opentrons
Conventions for the analyses snapshot testing framework in analyses-snapshot-testing/.
Opentrons/opentrons
CSS Modules conventions, Stylelint rules, design tokens (spacing, colors, typography, border-radius), and patterns for the Opentrons monorepo.
Opentrons/opentrons
Authoring and styling guidelines for the Opentrons /docs MkDocs project.
Opentrons/opentrons
Vite demo and Playwright + Applitools tests for packed @opentrons JS packages in js-package-testing/.
Works with
Categories
E2E testing conventions for Protocol Designer and Labware Library using Playwright + pytest in e2e-testing/. E2E Testing is an agent skill from Opentrons/opentrons. E2E testing conventions for Protocol Designer and Labware Library using Playwright + pytest in e2e-testing/.
E2E Testing fits situations like: modifying end-to-end tests; playwright tests.
Run `npx skills add Opentrons/opentrons --skill e2e-testing -a claude-code`. Or copy the skill folder (.cursor/skills/e2e-testing in Opentrons/opentrons) into .claude/skills/e2e-testing in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Opentrons/opentrons --skill e2e-testing -a codex`. Or copy the skill folder (.cursor/skills/e2e-testing in Opentrons/opentrons) into .agents/skills/e2e-testing in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Opentrons/opentrons --skill e2e-testing -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/e2e-testing, .gemini/skills/e2e-testing, .github/skills/e2e-testing and .opencode/skills/e2e-testing in your project.
Going by SKILL.md and its folder, E2E Testing needs the command-line tools its instructions call (make, node and uv) and credentials named APPLITOOLS_API_KEY. Our summary lists: Python 3; Node.js; A credential in APPLITOOLS_API_KEY.
SKILL.md names 4 domains. In commands or code: staging.designer.opentrons.com, staging.labware.opentrons.com, designer.opentrons.com and labware.opentrons.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
E2E Testing is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with E2E Testing: Claude Code QA (PramodDutta/qaskills, 232 stars), E2E Agent Browser (jh941213/my-cc-harness, 126 stars), Python Testing (macalbert/envilder, 138 stars) and Control UI E2E (openclaw/openclaw, 392k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Opentrons (a GitHub organization) maintains it in Opentrons/opentrons, which has 521 GitHub stars. The repository holds 17 skills in this directory. The repository was last updated on October 7, 2026.
Source: Opentrons/opentrons on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.