functional-testing
Use this skill when you need to design functional test plans or cases for business flows, UI, data, and integrations; triggers include functional testing and functional test cases.
Install
npx skills add https://github.com/naodeng/awesome-qa-skills/tree/main/skills/en/testing-types/functional-testing
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install naodeng-awesome-qa-skills@llmmart
git clone https://github.com/naodeng/awesome-qa-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole naodeng/awesome-qa-skills collection as a plugin from our marketplace. Git is the plain clone.
README
Functional Testing
Skill Overview
Need help with functional testing in a real project context; Need an output that can be used directly for execution, review, or follow-up.
How to Use
- Open
SKILL.mdin this folder and confirm this skill fits your task. - In your AI tool, call
@skill functional-testing, then add your real project context and goal. - If you need a specific output format (table, checklist, report), include it directly in your request.
One-Click Install Script
Run from the repository root:
macOS / Linux
bash ./scripts/install-skills-mac.sh --tool codex --lang en --skill functional-testing
Windows PowerShell
powershell -ExecutionPolicy Bypass -File .\scripts\install-skills-windows.ps1 -Tool codex -Lang en -Skill functional-testing
Skill manifest
Functional Testing (English)
Chinese version: See the corresponding Chinese skill.
When to Use
- Need help with functional testing in a real project context.
- Need an output that can be used directly for execution, review, or follow-up.
Workflow
- Read and follow the main prompt listed under Progressive disclosure (coverage, structure, quality bar).
- Add only project context that changes the result: scope, environment, constraints, risks, dependencies, expected deliverable.
- If input is incomplete, return a usable first draft and explicitly mark assumptions and gaps.
- Default to Markdown; switch formats only when the user asks.
Core Constraints
- Prioritize by risk / business impact — do not treat everything equally.
- Separate confirmed facts from current assumptions.
- Do not invent endpoints, fields, environments, or root causes the user did not provide.
- Keep output executable: concrete scenarios, clear priority, clear next steps.
Progressive Disclosure
- Before producing output, read and follow
prompts/functional-testing.md(minimum coverage, output structure, quality bar). - When Excel/CSV/JSON/Word is requested: read
output-formats.mdand honor the format. - When a ready-made template fits: use matching files under
output-templates/. - For deep framework/troubleshoot/schema notes: read only the relevant file(s) under
references/, do not load the whole directory. - For format conversion or helper checks: prefer existing
scripts/over reinventing. - For evaluating/regressing this skill: use
evals/with skill-up.
Pre-delivery Checklist
- Followed the main prompt's output structure
- Minimum coverage focus: scope, core flows, positive scenarios, negative scenarios, boundary scenarios, role or permission differences, data conditions, integration points, ... (details in main prompt)
- Covered the minimum checklist, or explained omissions
- High-risk items have explicit priority
- Did not invent details the user did not provide
- Assumptions and gaps are marked
Common Pitfalls
- Do not pretend completeness when scope/context is missing.
- Do not treat every item as equally important.
- Do not skip assumptions and information gaps.
- Do not dump generic theory unrelated to the current toolchain.
Files (awesome-qa-skills)
-
agents
-
openai.yaml 468 B
version: 1 metadata: key: "functional-testing" interface: display_name: "Functional Testing (English)" short_description: "Use this skill when you need to design functional test plans or cases for business flows, UI, data, and integrations; triggers include functional testing and f…" default_prompt: "Use the functional-testing skill to complete this testing task with structured outputs and practical next steps." policy: allow_implicit_invocation: true
-
-
evals
-
cases
-
basic-success.yaml 776 B
id: basic-success title: "Functional testing: executable plan with context" description: | With flows and roles, return prioritized functional coverage. input: prompt: | Use the functional-testing skill. Context: ecommerce place-order → pay → ship release. Env: SIT; roles: buyer, seller ops, warehouse. Known risk: payment callback timeouts. Produce a risk-focused functional test plan and mark assumptions/gaps. expect: must_contain: - "priority" - "payment" - "boundary" - "negative" - "assumption" must_not_contain: - "TODO" - "I cannot" judge: type: rule_based success: - output_contains: all: - "Task Understanding" - "Risk" - "boundary" - "negative" -
edge-incomplete-input.yaml 687 B
id: edge-incomplete-input title: "Functional testing: draft despite missing docs" description: | One-line requirements should still yield a draft with gaps. input: prompt: | Use functional-testing. Requirement: new release adds points redemption. No prototype or API docs. Give a usable first draft and list must-have information. expect: must_contain: - "assumption" - "Open Questions" - "gaps" - "assumptions" - "confirm" must_not_contain: - "TODO" - "I cannot" judge: type: rule_based success: - output_contains: all: - "assumption" - "Open Questions" - "gaps" - "assumptions" -
edge-risk-priority.yaml 666 B
id: edge-risk-priority title: "Functional testing: cut scope for a short window" description: | Many features + short window => P0 focus and deferrals. input: prompt: | Use functional-testing. Features: login, search, checkout, payment, coupons, points, tickets, admin reports. Half-day release window. Keep only critical paths and explain what can be deferred. expect: must_contain: - "P0" - "priority" - "critical path" - "defer" - "risk" must_not_contain: - "TODO" - "I cannot" judge: type: rule_based success: - output_contains: all: - "P0" - "defer" - "critical path"
-
-
eval.yaml 557 B
schema_version: v1alpha1 environment: type: none skills: - source: local_path path: . engine: name: claude_code # model is optional; omit to use engine default # model: # provider: anthropic # name: claude-sonnet-4-6 cases: files: - evals/cases/basic-success.yaml - evals/cases/edge-incomplete-input.yaml - evals/cases/edge-risk-priority.yaml defaults: timeout_seconds: 180 max_turns: 8 expect: exit_code: 0 must_not_contain: - "TODO" - "I cannot" report: formats: [json]
-
-
output-templates
-
template-csv.csv 206 B · in bundle
-
template-excel.tsv 358 B · in bundle
-
template-json.json 393 B
{ "meta": { "skill": "", "scope": "", "environment": "", "priority": "" }, "inputs": { "requirement": "", "constraints": [], "risks": [] }, "execution": [ { "step": 1, "action": "", "expected": "" } ], "results": { "status": "", "evidence": [], "defects": [] }, "next_actions": [ { "owner": "", "eta": "", "action": "" } ] } -
template-markdown.md 250 B
# QA Output Template ## Summary - Skill: - Scope: - Environment: - Priority: ## Inputs - Requirement: - Constraints: - Risks: ## Execution 1. Step 1 2. Step 2 3. Step 3 ## Results - Status: - Evidence: - Defects: ## Next Actions - Owner: - ETA: -
template-word.md 302 B
QA Report ========= 1. Basic Information - Skill: - Scope: - Environment: - Priority: 2. Requirement and Constraints - Requirement: - Constraints: - Risks: 3. Test/Review Process - Step 1: - Step 2: - Step 3: 4. Outcome - Status: - Evidence: - Defects: 5. Follow-up Plan - Owner: - ETA: - Action: -
template-xmind.md 317 B
# QA Output Mindmap - QA Output - Meta - Skill - Scope - Environment - Priority - Inputs - Requirement - Constraints - Risks - Execution - Step 1 - Step 2 - Step 3 - Results - Status - Evidence - Defects - Next Actions - Owner - ETA - Action
-
-
prompts
-
functional-testing.md 1.5 KB
# Functional Testing Prompt Design functional testing coverage for the features that matter most and make the result ready for execution. ## Role - Act as a senior QA and functional testing expert who focuses on business-critical behavior and realistic failure risk. ## Input - requirements, user stories, flows, UI designs, or release notes - in-scope modules, target users, environments, and constraints - existing defects, known weak areas, and current test assets ## What to do 1. Understand the core business flows and expected outcomes. 2. Prioritize high-value and failure-prone scenarios first. 3. Turn the scope into a practical testing plan or case list. ## Execution Rules - Cover normal, abnormal, and boundary behavior when relevant. - Group scenarios by user flow or business objective instead of random feature lists. - Call out areas that still need clarification before execution. ## Minimum Coverage Checklist Unless the user explicitly narrows the scope, make sure the result addresses these items: - scope - core flows - positive scenarios - negative scenarios - boundary scenarios - role or permission differences - data conditions - integration points - priority by risk - out-of-scope or unclear items ## Output Return the result in this order: ### 1. Task Understanding ### 2. Risk and Priority ### 3. Core Functional Coverage ### 4. Key Scenario List ### 5. Execution Notes ### 6. Open Questions ## Quality Bar - Be specific about scenarios. - Do not produce a flat checklist with no prioritization. - Avoid generic filler.
-
-
references
-
local
-
FAQ.md 534 B
# Archived Local Reference This file is a lightweight legacy note. The previous long snapshot was removed to avoid duplicate and outdated guidance. ## Use Instead - Main prompt: `prompts/functional-testing.md` - Main entry: `SKILL.md` - Output format guide: `output-formats.md` ## Notes - Keep using the current prompt and `SKILL.md` as the source of truth. - Load `references/`, `examples/`, or `scripts/` only when the task really needs extra detail. - Do not rely on this file for the latest prompt wording or workflow rules. -
Users-nao.deng-awsomeCode-awesome-qa-skills-skills-testing-types-functional-testing-examples-playwright-login.md 596 B
# Local Example Collection Reference This file points to an example collection that used to be stored as a larger snapshot. ## What It Is - A local note for example-related materials. - Useful only when you need extra example context beyond the main prompt. ## Prefer These Files - `SKILL.md` - `prompts/functional-testing.md` - `references/` ## Notes - This file is now a short local reference instead of a full snapshot copy. - Use it only when you need extra background beyond the main prompt and `SKILL.md`. - If the current prompt conflicts with this file, follow the current prompt. -
Users-nao.deng-awsomeCode-awesome-qa-skills-skills-testing-types-functional-testing-examples.md 596 B
# Local Example Collection Reference This file points to an example collection that used to be stored as a larger snapshot. ## What It Is - A local note for example-related materials. - Useful only when you need extra example context beyond the main prompt. ## Prefer These Files - `SKILL.md` - `prompts/functional-testing.md` - `references/` ## Notes - This file is now a short local reference instead of a full snapshot copy. - Use it only when you need extra background beyond the main prompt and `SKILL.md`. - If the current prompt conflicts with this file, follow the current prompt.
-
-
output-formats.md 91 B
# Output Formats Describe recommended output formats for functional testing deliverables. -
troubleshooting.md 3.6 KB
## Troubleshooting ### Issue 1: Code Examples Won't Run **Symptoms:** Error `Cannot find module` or `Command not found` when running examples **Solution:** 1. Ensure dependencies are installed: ```bash cd examples/playwright-login npm install ``` 2. Check Node.js version (requires >= 16): ```bash node --version ``` 3. If using Playwright, install browsers: ```bash npx playwright install ``` ### Issue 2: Incomplete Test Case Design **Symptoms:** Low test coverage, missing important scenarios **Solution:** 1. Use requirements-analysis skill first to analyze requirements 2. Refer to "Test Coverage Dimensions" section in the prompt 3. Use test design methods: - Equivalence partitioning - Boundary value analysis - Decision table testing - State transition testing 4. Checklist: - [ ] Normal scenarios - [ ] Exception scenarios - [ ] Boundary values - [ ] Error handling - [ ] Accessibility - [ ] Security ### Issue 3: Output Format Not as Expected **Symptoms:** Generated test cases have wrong format or missing fields **Solution:** 1. Clearly specify format requirements at the end of request: ``` Please output as tab-separated table for pasting into Excel ``` 2. Refer to examples in [output-formats.md](output-formats.md) 3. Use format conversion tool (to be implemented): ```bash ./tools/format-converter.sh input.md --to=excel ``` ### Issue 4: Unstable Test Execution **Symptoms:** Tests sometimes pass, sometimes fail **Solution:** 1. Use explicit waits instead of fixed delays: ```typescript // ✅ Recommended await expect(element).toBeVisible(); // ❌ Not recommended await page.waitForTimeout(3000); ``` 2. Wait for network requests to complete: ```typescript await page.waitForResponse(resp => resp.url().includes('/api')); ``` 3. Use retry mechanism (Playwright config): ```typescript retries: 2 ``` ### Issue 5: Cannot Locate Element **Symptoms:** Test error `Element not found` or `Timeout` **Solution:** 1. Check if element is in iframe: ```typescript const frame = page.frameLocator('iframe'); await frame.locator('[data-testid="element"]').click(); ``` 2. Wait for element to appear: ```typescript await page.waitForSelector('[data-testid="element"]'); ``` 3. Use more reliable locators: ```typescript // ✅ Recommended: data-testid page.locator('[data-testid="login-button"]') // ✅ Recommended: role page.getByRole('button', { name: 'Login' }) // ❌ Not recommended: CSS class page.locator('.btn-primary') ``` ### Issue 6: Slow Test Execution **Symptoms:** Test suite takes too long to execute **Solution:** 1. Enable parallel execution: ```typescript // playwright.config.ts fullyParallel: true, workers: 4, ``` 2. Optimize wait strategies, avoid unnecessary waits 3. Use test data caching 4. Consider using API to set up test preconditions ### Issue 7: CI/CD Environment Test Failures **Symptoms:** Tests pass locally but fail in CI **Solution:** 1. Check environment differences (browser version, screen resolution) 2. Increase timeout for CI environment 3. Enable failure retry: ```typescript retries: process.env.CI ? 2 : 0 ``` 4. Review CI logs, screenshots, and videos 5. Use Docker containers to ensure environment consistency ### Get More Help If the issue persists: 1. Check [FAQ.md](local/FAQ.md) 2. Check example README.md files 3. Search [GitHub Issues](https://github.com/naodeng/awesome-qa-skills/issues) 4. Submit a new Issue with detailed information **Related:** api-testing, test-case-writing, test-strategy, automation-testing.
-
-
scripts
-
batch_convert_templates.py 2.7 KB
#!/usr/bin/env python3 import argparse import subprocess import sys from pathlib import Path def detect_from(file: Path) -> str: ext = file.suffix.lower() if file.name.endswith('.word.md'): return 'markdown' return { '.md': 'markdown', '.markdown': 'markdown', '.json': 'json', '.csv': 'csv', '.tsv': 'excel', '.docx': 'word', '.xlsx': 'excel', '.xmind': 'xmind', }.get(ext, 'markdown') def run_convert(convert_script: Path, src: Path, to_fmt: str, out: Path) -> int: cmd = [sys.executable, str(convert_script), str(src), '--from', detect_from(src), '--to', to_fmt, '--output', str(out)] return subprocess.call(cmd) def main() -> None: parser = argparse.ArgumentParser(description='Batch convert all template files into target formats.') parser.add_argument('--templates-dir', type=Path, default=Path('output-templates')) parser.add_argument('--artifacts-dir', type=Path, default=Path('artifacts')) parser.add_argument('--targets', default='word,excel,xmind,json,csv,markdown', help='comma-separated target formats') parser.add_argument('--skip-same', action='store_true', help='skip conversion when source format equals target format') args = parser.parse_args() cwd = Path.cwd() templates_dir = (cwd / args.templates_dir).resolve() artifacts_dir = (cwd / args.artifacts_dir).resolve() artifacts_dir.mkdir(parents=True, exist_ok=True) local_convert = (Path(__file__).resolve().parent / 'convert_formats.py').resolve() targets = [t.strip() for t in args.targets.split(',') if t.strip()] if not templates_dir.exists(): raise SystemExit(f'templates directory not found: {templates_dir}') files = [p for p in sorted(templates_dir.iterdir()) if p.is_file()] total = 0 failed = 0 for src in files: src_fmt = detect_from(src) for to_fmt in targets: if args.skip_same and src_fmt == to_fmt: continue out_ext = { 'json': '.json', 'csv': '.csv', 'excel': '.tsv', 'markdown': '.md', 'word': '.word.md', 'xmind': '.xmind.md', }[to_fmt] out = artifacts_dir / f"{src.stem}.to-{to_fmt}{out_ext}" total += 1 rc = run_convert(local_convert, src, to_fmt, out) if rc != 0: failed += 1 print(f'[FAILED] {src.name} -> {to_fmt}') else: print(f'[OK] {src.name} -> {out.name}') print(f'\nDone. total={total}, failed={failed}, artifacts={artifacts_dir}') if failed: raise SystemExit(1) if __name__ == '__main__': main() -
convert_formats.py 10.4 KB
#!/usr/bin/env python3 import argparse import csv import json import re import zipfile from pathlib import Path from typing import Any from xml.etree import ElementTree as ET # ---- parsing ---- def parse_markdown(path: Path) -> dict[str, Any]: text = path.read_text(encoding="utf-8", errors="ignore") lines = text.splitlines() headings: list[dict[str, Any]] = [] for line in lines: m = re.match(r"^(#{1,6})\s+(.*)$", line.strip()) if m: headings.append({"level": len(m.group(1)), "title": m.group(2).strip()}) return {"title": headings[0]["title"] if headings else path.stem, "headings": headings, "text": text} def parse_json(path: Path) -> dict[str, Any]: data = json.loads(path.read_text(encoding="utf-8", errors="ignore")) return {"title": path.stem, "data": data} def parse_csv_file(path: Path) -> dict[str, Any]: with path.open("r", encoding="utf-8", errors="ignore", newline="") as f: reader = csv.DictReader(f) rows = list(reader) return {"title": path.stem, "columns": reader.fieldnames or [], "rows": rows} def parse_docx(path: Path) -> dict[str, Any]: paragraphs: list[str] = [] with zipfile.ZipFile(path) as zf: with zf.open("word/document.xml") as f: root = ET.fromstring(f.read()) ns = {"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"} for p in root.findall(".//w:p", ns): texts = [t.text for t in p.findall(".//w:t", ns) if t.text] s = "".join(texts).strip() if s: paragraphs.append(s) return {"title": path.stem, "paragraphs": paragraphs} def _shared_strings(zf: zipfile.ZipFile) -> list[str]: out: list[str] = [] try: with zf.open("xl/sharedStrings.xml") as f: root = ET.fromstring(f.read()) ns = {"a": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"} for si in root.findall(".//a:si", ns): out.append("".join((t.text or "") for t in si.findall(".//a:t", ns))) except KeyError: pass return out def parse_xlsx(path: Path) -> dict[str, Any]: rows: list[list[str]] = [] with zipfile.ZipFile(path) as zf: shared = _shared_strings(zf) with zf.open("xl/worksheets/sheet1.xml") as f: root = ET.fromstring(f.read()) ns = {"a": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"} for row in root.findall(".//a:sheetData/a:row", ns): vals = [] for c in row.findall("a:c", ns): t = c.attrib.get("t") v = c.find("a:v", ns) if v is None or v.text is None: vals.append("") elif t == "s": idx = int(v.text) vals.append(shared[idx] if 0 <= idx < len(shared) else "") else: vals.append(v.text) rows.append(vals) return {"title": path.stem, "rows": rows} def parse_xmind(path: Path) -> dict[str, Any]: with zipfile.ZipFile(path) as zf: names = set(zf.namelist()) topics: list[str] = [] if "content.json" in names: data = json.loads(zf.read("content.json").decode("utf-8", errors="ignore")) def walk(node: Any): if isinstance(node, dict): t = node.get("title") if isinstance(t, str) and t.strip(): topics.append(t.strip()) for k in ("children", "topics", "rootTopic", "attached"): walk(node.get(k)) elif isinstance(node, list): for i in node: walk(i) walk(data) elif "content.xml" in names: root = ET.fromstring(zf.read("content.xml")) topics = [e.text.strip() for e in root.findall(".//title") if e.text and e.text.strip()] else: raise ValueError("Unsupported XMind package structure") return {"title": topics[0] if topics else path.stem, "topics": topics} def detect_in_format(path: Path, forced: str | None) -> str: if forced and forced != "auto": return forced return { ".md": "markdown", ".markdown": "markdown", ".json": "json", ".csv": "csv", ".docx": "word", ".xlsx": "excel", ".xmind": "xmind", ".tsv": "excel", }.get(path.suffix.lower(), "markdown") def normalize(parsed: dict[str, Any]) -> dict[str, Any]: title = parsed.get("title") or "QA Output" sections: list[dict[str, Any]] = [] if "text" in parsed: sections.append({"name": "content", "items": [{"key": "text", "value": parsed["text"]}]}) if "headings" in parsed: sections.append({"name": "headings", "items": [{"key": "heading", "value": h.get("title", "")} for h in parsed["headings"]]}) if "data" in parsed: data = parsed["data"] if isinstance(data, dict): items = [{"key": k, "value": v} for k, v in list(data.items())[:100]] sections.append({"name": "json_object", "items": items}) elif isinstance(data, list): sections.append({"name": "json_array", "items": [{"key": "row", "value": v} for v in data[:200]]}) else: sections.append({"name": "json_value", "items": [{"key": "value", "value": data}]}) if "rows" in parsed: rows = parsed["rows"] sections.append({"name": "rows", "items": [{"key": f"row_{i+1}", "value": r} for i, r in enumerate(rows[:200])]}) if "columns" in parsed: sections.append({"name": "columns", "items": [{"key": "column", "value": c} for c in parsed["columns"]]}) if "paragraphs" in parsed: sections.append({"name": "paragraphs", "items": [{"key": f"p{i+1}", "value": p} for i, p in enumerate(parsed["paragraphs"][:200])]}) if "topics" in parsed: sections.append({"name": "topics", "items": [{"key": "topic", "value": t} for t in parsed["topics"][:300]]}) return {"title": title, "sections": sections} # ---- writers ---- def write_json(model: dict[str, Any], output: Path) -> None: output.write_text(json.dumps(model, ensure_ascii=False, indent=2), encoding="utf-8") def _scalar(v: Any) -> str: if isinstance(v, (dict, list)): return json.dumps(v, ensure_ascii=False) return str(v) def write_csv(model: dict[str, Any], output: Path) -> None: with output.open("w", encoding="utf-8", newline="") as f: writer = csv.writer(f) writer.writerow(["section", "key", "value"]) for s in model.get("sections", []): for item in s.get("items", []): writer.writerow([s.get("name", ""), item.get("key", ""), _scalar(item.get("value", ""))]) def write_excel_tsv(model: dict[str, Any], output: Path) -> None: lines = ["Section\tKey\tValue"] for s in model.get("sections", []): for item in s.get("items", []): lines.append(f"{s.get('name','')}\t{item.get('key','')}\t{_scalar(item.get('value','')).replace(chr(9), ' ')}") output.write_text("\n".join(lines) + "\n", encoding="utf-8") def write_markdown(model: dict[str, Any], output: Path) -> None: lines = [f"# {model.get('title', 'QA Output')}", ""] for s in model.get("sections", []): lines.append(f"## {s.get('name', 'section')}") for item in s.get("items", []): lines.append(f"- **{item.get('key','key')}**: {_scalar(item.get('value',''))}") lines.append("") output.write_text("\n".join(lines).rstrip() + "\n", encoding="utf-8") def write_word_md(model: dict[str, Any], output: Path) -> None: lines = [model.get("title", "QA Output"), "=" * len(model.get("title", "QA Output")), ""] idx = 1 for s in model.get("sections", []): lines.append(f"{idx}. {s.get('name', 'section').replace('_', ' ').title()}") for item in s.get("items", []): lines.append(f"- {item.get('key','key')}: {_scalar(item.get('value',''))}") lines.append("") idx += 1 output.write_text("\n".join(lines).rstrip() + "\n", encoding="utf-8") def write_xmind_md(model: dict[str, Any], output: Path) -> None: lines = [f"# {model.get('title', 'QA Output')}", "", f"- {model.get('title', 'QA Output')}"] for s in model.get("sections", []): lines.append(f" - {s.get('name', 'section')}") for item in s.get("items", []): lines.append(f" - {item.get('key','key')}: {_scalar(item.get('value',''))}") output.write_text("\n".join(lines).rstrip() + "\n", encoding="utf-8") def default_output(input_path: Path, to_fmt: str) -> Path: ext = { "json": ".json", "csv": ".csv", "excel": ".tsv", "markdown": ".md", "word": ".word.md", "xmind": ".xmind.md", }[to_fmt] return input_path.with_name(input_path.stem + ".converted" + ext) def main() -> None: parser = argparse.ArgumentParser(description="Convert QA output files between common formats") parser.add_argument("input", type=Path, help="Input file path") parser.add_argument("--from", dest="from_fmt", default="auto", choices=["auto", "word", "excel", "xmind", "json", "csv", "markdown"]) parser.add_argument("--to", required=True, choices=["word", "excel", "xmind", "json", "csv", "markdown"]) parser.add_argument("--output", type=Path, help="Output file path") args = parser.parse_args() in_fmt = detect_in_format(args.input, args.from_fmt) if in_fmt == "word": parsed = parse_docx(args.input) elif in_fmt == "excel": if args.input.suffix.lower() == ".tsv": rows = [line.rstrip("\n").split("\t") for line in args.input.read_text(encoding="utf-8", errors="ignore").splitlines() if line] parsed = {"title": args.input.stem, "rows": rows} else: parsed = parse_xlsx(args.input) elif in_fmt == "xmind": parsed = parse_xmind(args.input) elif in_fmt == "json": parsed = parse_json(args.input) elif in_fmt == "csv": parsed = parse_csv_file(args.input) else: parsed = parse_markdown(args.input) model = normalize(parsed) output = args.output or default_output(args.input, args.to) if args.to == "json": write_json(model, output) elif args.to == "csv": write_csv(model, output) elif args.to == "excel": write_excel_tsv(model, output) elif args.to == "markdown": write_markdown(model, output) elif args.to == "word": write_word_md(model, output) else: write_xmind_md(model, output) print(str(output)) if __name__ == "__main__": main() -
convert_output_formats.py 255 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL] + sys.argv[1:])) -
convert_to_csv.py 270 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL, '--to', 'csv'] + sys.argv[1:])) -
convert_to_excel.py 272 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL, '--to', 'excel'] + sys.argv[1:])) -
convert_to_json.py 271 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL, '--to', 'json'] + sys.argv[1:])) -
convert_to_markdown.py 275 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL, '--to', 'markdown'] + sys.argv[1:])) -
convert_to_word.py 271 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL, '--to', 'word'] + sys.argv[1:])) -
convert_to_xmind.py 272 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'convert_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL, '--to', 'xmind'] + sys.argv[1:])) -
parse_csv.py 272 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL, '--format', 'csv'] + sys.argv[1:])) -
parse_excel.py 274 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL, '--format', 'excel'] + sys.argv[1:])) -
parse_formats.py 5.9 KB
#!/usr/bin/env python3 import argparse import csv import json import re import zipfile from pathlib import Path from typing import Any from xml.etree import ElementTree as ET def parse_markdown(path: Path) -> dict[str, Any]: text = path.read_text(encoding="utf-8", errors="ignore") headings = [] for line in text.splitlines(): m = re.match(r"^(#{1,6})\s+(.*)$", line.strip()) if m: headings.append({"level": len(m.group(1)), "title": m.group(2).strip()}) return {"format": "markdown", "headings": headings, "preview": text[:500]} def parse_json(path: Path) -> dict[str, Any]: data = json.loads(path.read_text(encoding="utf-8", errors="ignore")) if isinstance(data, dict): shape = {"type": "object", "keys": list(data.keys())[:50]} elif isinstance(data, list): shape = {"type": "array", "size": len(data)} else: shape = {"type": type(data).__name__} return {"format": "json", "shape": shape, "data": data} def parse_csv_file(path: Path) -> dict[str, Any]: with path.open("r", encoding="utf-8", errors="ignore", newline="") as f: reader = csv.DictReader(f) rows = list(reader) return { "format": "csv", "columns": reader.fieldnames or [], "row_count": len(rows), "sample_rows": rows[:10], } def parse_docx(path: Path) -> dict[str, Any]: paragraphs = [] with zipfile.ZipFile(path) as zf: with zf.open("word/document.xml") as f: root = ET.fromstring(f.read()) ns = {"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"} for p in root.findall(".//w:p", ns): texts = [t.text for t in p.findall(".//w:t", ns) if t.text] joined = "".join(texts).strip() if joined: paragraphs.append(joined) return {"format": "word", "paragraph_count": len(paragraphs), "paragraphs": paragraphs[:100]} def _read_shared_strings(zf: zipfile.ZipFile) -> list[str]: strings = [] try: with zf.open("xl/sharedStrings.xml") as f: root = ET.fromstring(f.read()) ns = {"a": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"} for si in root.findall(".//a:si", ns): parts = [t.text or "" for t in si.findall(".//a:t", ns)] strings.append("".join(parts)) except KeyError: pass return strings def parse_xlsx(path: Path) -> dict[str, Any]: rows_out: list[list[str]] = [] with zipfile.ZipFile(path) as zf: shared = _read_shared_strings(zf) with zf.open("xl/worksheets/sheet1.xml") as f: root = ET.fromstring(f.read()) ns = {"a": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"} for row in root.findall(".//a:sheetData/a:row", ns): vals = [] for c in row.findall("a:c", ns): cell_type = c.attrib.get("t") v = c.find("a:v", ns) if v is None or v.text is None: vals.append("") continue if cell_type == "s": idx = int(v.text) vals.append(shared[idx] if 0 <= idx < len(shared) else "") else: vals.append(v.text) rows_out.append(vals) return {"format": "excel", "row_count": len(rows_out), "sample_rows": rows_out[:20]} def parse_xmind(path: Path) -> dict[str, Any]: with zipfile.ZipFile(path) as zf: names = set(zf.namelist()) if "content.json" in names: data = json.loads(zf.read("content.json").decode("utf-8", errors="ignore")) titles: list[str] = [] def walk(node: Any): if isinstance(node, dict): title = node.get("title") if isinstance(title, str) and title.strip(): titles.append(title.strip()) for k in ("children", "topics", "rootTopic", "attached"): walk(node.get(k)) elif isinstance(node, list): for i in node: walk(i) walk(data) return {"format": "xmind", "topic_count": len(titles), "topics": titles[:200]} if "content.xml" in names: root = ET.fromstring(zf.read("content.xml")) titles = [el.text.strip() for el in root.findall(".//title") if el.text and el.text.strip()] return {"format": "xmind", "topic_count": len(titles), "topics": titles[:200]} raise ValueError("Unsupported XMind package structure") def detect_format(path: Path, forced: str | None) -> str: if forced and forced != "auto": return forced ext = path.suffix.lower() return { ".md": "markdown", ".markdown": "markdown", ".json": "json", ".csv": "csv", ".docx": "word", ".xlsx": "excel", ".xmind": "xmind", }.get(ext, "markdown") def main() -> None: parser = argparse.ArgumentParser(description="Parse common QA output formats into normalized JSON") parser.add_argument("input", type=Path, help="Input file path") parser.add_argument("--format", default="auto", choices=["auto", "word", "excel", "xmind", "json", "csv", "markdown"]) parser.add_argument("--output", type=Path, help="Output JSON path (default: stdout)") args = parser.parse_args() fmt = detect_format(args.input, args.format) if fmt == "word": result = parse_docx(args.input) elif fmt == "excel": result = parse_xlsx(args.input) elif fmt == "xmind": result = parse_xmind(args.input) elif fmt == "json": result = parse_json(args.input) elif fmt == "csv": result = parse_csv_file(args.input) else: result = parse_markdown(args.input) result["source"] = str(args.input) out = json.dumps(result, ensure_ascii=False, indent=2) if args.output: args.output.write_text(out, encoding="utf-8") else: print(out) if __name__ == "__main__": main() -
parse_json.py 273 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL, '--format', 'json'] + sys.argv[1:])) -
parse_markdown.py 277 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL, '--format', 'markdown'] + sys.argv[1:])) -
parse_output_formats.py 253 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL] + sys.argv[1:])) -
parse_word.py 273 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL, '--format', 'word'] + sys.argv[1:])) -
parse_xmind.py 274 B
#!/usr/bin/env python3 import os import subprocess import sys LOCAL = os.path.normpath(os.path.join(os.path.dirname(__file__), 'parse_formats.py')) if __name__ == '__main__': raise SystemExit(subprocess.call([sys.executable, LOCAL, '--format', 'xmind'] + sys.argv[1:]))
-
-
output-formats.md 1.1 KB
# Output Format Options This skill **defaults to Markdown**. To get **Excel**, **CSV**, or **JSON**, add a short instruction at the **end of your request**. --- ## 1. Markdown (default) The AI follows the functional-testing Standard-version Markdown template (test plan, test cases, etc.). --- ## 2. Excel format **How to request:** e.g. “Please also output the test cases / test plan as **tab-separated values** so I can paste them into Excel.” **Conventions:** First row = header; columns separated by **Tab**; paste into Excel to split columns. --- ## 3. CSV format **How to request:** e.g. “Please output the result as **CSV** (comma-separated, header row first).” **Conventions:** Header row first; comma `,` between columns; wrap cells containing comma or newline in `"`. --- ## 4. JSON format **How to request:** e.g. “Please output the test cases / plan as **JSON**.” **Conventions:** Valid JSON; table-like content as array of objects with fields consistent with the Markdown (e.g. id, title, priority, preconditions, steps, expectedResult). --- See repo `_output-formats-template-en.md` for generic examples. -
quick-start.md 2.1 KB
# Functional Testing: Quick Start Use the `functional-testing` Skill to design executable functional coverage around business-critical user journeys. ## 1. Prepare the Minimum Context Provide what is available from this list: - requirements - user flows - roles - business rules - environment - historical defects - scope, version, environment, time budget, and prohibited actions - known failures, existing tests, and evidence links If some information is unavailable, say so explicitly. The Skill should still return a bounded first pass with assumptions and open questions. ## 2. Invoke the Skill ```text @skill functional-testing Scenario: Test registration, verification, login, password recovery, and account lockout. Prioritize the highest risks, distinguish facts from assumptions, and provide an executable result with evidence requirements and open questions. ``` ## 3. Follow the Execution Flow 1. Confirm the objective, subject, scope, and success criteria. 2. Audit the completeness and credibility of the supplied material. 3. Identify failure modes and rank them by impact, likelihood, and detectability. 4. Produce concrete scenarios, checks, or decisions with expected results. 5. Record evidence gaps, residual risk, and the smallest useful next action. ## 4. Minimum Coverage Unless the request narrows scope, cover: - happy paths - failures - boundaries - state transitions - permissions - data - integrations - priorities - confirmed facts, working assumptions, and open questions - P0/P1 priorities and the rationale for lower-priority deferral - blockers, stop conditions, and residual risk ## 5. Review the Result - Every high-risk item has a concrete failure mode and expected behavior. - Priorities are justified rather than evenly distributed. - No field, API, metric, environment, or execution result is invented. - The artifact can be executed or reviewed without guessing the next step. - Production, security, and privacy work uses least privilege and sanitized data. ## 6. Continue Add missing evidence and ask the Skill to refine the same artifact. Keep confirmed facts separate from newly introduced assumptions so changes remain reviewable. -
README.md 820 B
# Functional Testing ## Skill Overview Need help with functional testing in a real project context; Need an output that can be used directly for execution, review, or follow-up. ## How to Use 1. Open `SKILL.md` in this folder and confirm this skill fits your task. 2. In your AI tool, call `@skill functional-testing`, then add your real project context and goal. 3. If you need a specific output format (table, checklist, report), include it directly in your request. ## One-Click Install Script Run from the repository root: ### macOS / Linux ```bash bash ./scripts/install-skills-mac.sh --tool codex --lang en --skill functional-testing ``` ### Windows PowerShell ```powershell powershell -ExecutionPolicy Bypass -File .\scripts\install-skills-windows.ps1 -Tool codex -Lang en -Skill functional-testing ``` -
SKILL.md 2.5 KB
--- name: functional-testing description: Use this skill when you need to design functional test plans or cases for business flows, UI, data, and integrations; triggers include functional testing and functional test cases. --- # Functional Testing (English) **Chinese version:** See the corresponding Chinese skill. ## When to Use - Need help with functional testing in a real project context. - Need an output that can be used directly for execution, review, or follow-up. ## Workflow 1. Read and follow the main prompt listed under Progressive disclosure (coverage, structure, quality bar). 2. Add only project context that changes the result: scope, environment, constraints, risks, dependencies, expected deliverable. 3. If input is incomplete, return a usable first draft and explicitly mark assumptions and gaps. 4. Default to Markdown; switch formats only when the user asks. ## Core Constraints - Prioritize by risk / business impact — do not treat everything equally. - Separate confirmed facts from current assumptions. - Do not invent endpoints, fields, environments, or root causes the user did not provide. - Keep output executable: concrete scenarios, clear priority, clear next steps. ## Progressive Disclosure - Before producing output, read and follow `prompts/functional-testing.md` (minimum coverage, output structure, quality bar). - When Excel/CSV/JSON/Word is requested: read `output-formats.md` and honor the format. - When a ready-made template fits: use matching files under `output-templates/`. - For deep framework/troubleshoot/schema notes: read only the relevant file(s) under `references/`, do not load the whole directory. - For format conversion or helper checks: prefer existing `scripts/` over reinventing. - For evaluating/regressing this skill: use `evals/` with skill-up. ## Pre-delivery Checklist - [ ] Followed the main prompt's output structure - [ ] Minimum coverage focus: scope, core flows, positive scenarios, negative scenarios, boundary scenarios, role or permission differences, data conditions, integration points, ... (details in main prompt) - [ ] Covered the minimum checklist, or explained omissions - [ ] High-risk items have explicit priority - [ ] Did not invent details the user did not provide - [ ] Assumptions and gaps are marked ## Common Pitfalls - Do not pretend completeness when scope/context is missing. - Do not treat every item as equally important. - Do not skip assumptions and information gaps. - Do not dump generic theory unrelated to the current toolchain. -
tutorial.md 4.1 KB
# Functional Testing: Practical Tutorial This tutorial shows how to design executable functional coverage around business-critical user journeys with a repeatable, evidence-driven workflow. ## Learning Objectives By the end, you should be able to: - frame a bounded testing objective; - identify the evidence needed before making decisions; - turn domain risk into executable scenarios and assertions; - choose priorities without treating every check as equally important; - report residual risk without inventing certainty. ## Scenario Test registration, verification, login, password recovery, and account lockout. Use the scenario as a starting point. Replace it with real project material whenever possible. ## Step 1: Establish the Input Contract Collect: - requirements - user flows - roles - business rules - environment - historical defects - the exact build, version, environment, and test window - authorized accounts, sanitized data, and allowed side effects - existing tests, defects, monitoring, and rollback constraints Create three lists before analysis: 1. **Confirmed facts** — directly supported by supplied material. 2. **Working assumptions** — necessary for a first pass but not yet proven. 3. **Open questions** — missing information that changes scope or risk. ## Step 2: Build the Risk Model For each capability or user journey, record: | Field | Meaning | | --- | --- | | Failure mode | What can go wrong | | Impact | User, business, security, or operational consequence | | Likelihood | Why the failure is plausible | | Detectability | Whether existing checks or telemetry reveal it | | Priority | P0, P1, P2, or P3 with rationale | | Evidence | What would confirm correct or incorrect behavior | Start with irreversible data loss, security exposure, financial impact, critical journey failure, and release blockers. ## Step 3: Design Coverage Minimum domain coverage: - happy paths - failures - boundaries - state transitions - permissions - data - integrations - priorities For each important scenario, specify: ```text Preconditions: Test data: Action or stimulus: Expected behavior: Evidence to capture: Cleanup or rollback: ``` Avoid generic statements such as “test positive and negative cases” unless the concrete cases are listed. ## Step 4: Execute Safely - Use the lowest environment and privilege level that can answer the question. - Prefer mocks, sandboxes, dry runs, and synthetic or masked data. - Do not run destructive production actions without explicit authorization. - Record timestamps, versions, configuration, and identifiers needed for reproduction. - Stop when a predefined safety, data-integrity, or customer-impact condition is met. ## Step 5: Interpret Evidence Separate observation from explanation: ```text Observation: what the system or test actually showed Hypothesis: a possible explanation Counter-evidence: facts that weaken the hypothesis Verification: the smallest experiment that can distinguish alternatives Conclusion: only what the available evidence supports ``` One failure message, high resource value, or correlated metric is not automatically a root cause. ## Step 6: Report the Result Use this order: 1. Task understanding and scope 2. Input audit 3. Risks and priorities 4. Executed or proposed coverage 5. Results and evidence 6. Blockers and residual risk 7. Next actions and owners ## Reusable Request ```text @skill functional-testing Analyze this real project context using the Skill's complete prompt contract. Separate confirmed facts, working assumptions, and open questions. Prioritize P0/P1 risks, provide executable scenarios with expected results and evidence, and state stop conditions and residual risk. ``` ## Completion Checklist - [ ] The objective and success criteria are explicit. - [ ] The environment, version, and data boundary are recorded. - [ ] High-risk paths have concrete scenarios and expected results. - [ ] Evidence supports conclusions. - [ ] Missing information and assumptions remain visible. - [ ] Cleanup, rollback, or human-handoff conditions are defined. - [ ] The next action is small, owned, and verifiable.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.