qa-skills 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +168 -0
- package/bin/cli.js +42 -0
- package/dist/agents/registry.d.ts +5 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +101 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/types.d.ts +9 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +2 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/dependencies.d.ts +21 -0
- package/dist/dependencies.d.ts.map +1 -0
- package/dist/dependencies.js +125 -0
- package/dist/dependencies.js.map +1 -0
- package/dist/installer.d.ts +25 -0
- package/dist/installer.d.ts.map +1 -0
- package/dist/installer.js +437 -0
- package/dist/installer.js.map +1 -0
- package/dist/scaffold.d.ts +27 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +182 -0
- package/dist/scaffold.js.map +1 -0
- package/package.json +40 -0
- package/skills/qa-accessibility-test-writer/SKILL.md +127 -0
- package/skills/qa-accessibility-test-writer/references/axe-core-patterns.md +349 -0
- package/skills/qa-accessibility-test-writer/references/best-practices.md +184 -0
- package/skills/qa-accessibility-test-writer/references/wcag-tests.md +331 -0
- package/skills/qa-api-contract-curator/SKILL.md +104 -0
- package/skills/qa-api-contract-curator/references/breaking-changes.md +363 -0
- package/skills/qa-api-contract-curator/references/openapi-structure.md +404 -0
- package/skills/qa-browser-data-collector/SKILL.md +132 -0
- package/skills/qa-browser-data-collector/references/data-collection-checklist.md +91 -0
- package/skills/qa-browser-data-collector/references/playwright-mcp-patterns.md +113 -0
- package/skills/qa-bug-ticket-creator/SKILL.md +148 -0
- package/skills/qa-bug-ticket-creator/references/bug-report-format.md +149 -0
- package/skills/qa-bug-ticket-creator/references/severity-guide.md +81 -0
- package/skills/qa-bug-ticket-creator/templates/bug-ticket-template.md +39 -0
- package/skills/qa-changelog-analyzer/SKILL.md +134 -0
- package/skills/qa-changelog-analyzer/references/git-analysis-patterns.md +138 -0
- package/skills/qa-changelog-analyzer/references/impact-mapping.md +120 -0
- package/skills/qa-clickup-integration/SKILL.md +166 -0
- package/skills/qa-clickup-integration/references/api-patterns.md +102 -0
- package/skills/qa-clickup-integration/references/field-mapping.md +71 -0
- package/skills/qa-codeceptjs-writer/SKILL.md +136 -0
- package/skills/qa-codeceptjs-writer/references/best-practices.md +207 -0
- package/skills/qa-codeceptjs-writer/references/config.md +255 -0
- package/skills/qa-codeceptjs-writer/references/patterns.md +285 -0
- package/skills/qa-coverage-analyzer/SKILL.md +166 -0
- package/skills/qa-coverage-analyzer/references/best-practices.md +142 -0
- package/skills/qa-coverage-analyzer/references/coverage-dimensions.md +155 -0
- package/skills/qa-coverage-analyzer/references/tools.md +204 -0
- package/skills/qa-cypress-writer/SKILL.md +134 -0
- package/skills/qa-cypress-writer/references/assertions.md +121 -0
- package/skills/qa-cypress-writer/references/best-practices.md +82 -0
- package/skills/qa-cypress-writer/references/config.md +121 -0
- package/skills/qa-cypress-writer/references/patterns.md +170 -0
- package/skills/qa-data-factory/SKILL.md +126 -0
- package/skills/qa-data-factory/references/factory-patterns.md +164 -0
- package/skills/qa-data-factory/references/faker-guide.md +131 -0
- package/skills/qa-diagram-generator/SKILL.md +125 -0
- package/skills/qa-diagram-generator/references/c4-model.md +53 -0
- package/skills/qa-diagram-generator/references/charts.md +58 -0
- package/skills/qa-diagram-generator/references/class-diagram.md +85 -0
- package/skills/qa-diagram-generator/references/er-diagram.md +69 -0
- package/skills/qa-diagram-generator/references/flowchart.md +92 -0
- package/skills/qa-diagram-generator/references/from-screenshot.md +45 -0
- package/skills/qa-diagram-generator/references/gantt.md +49 -0
- package/skills/qa-diagram-generator/references/journey.md +50 -0
- package/skills/qa-diagram-generator/references/mindmap.md +75 -0
- package/skills/qa-diagram-generator/references/sequence.md +69 -0
- package/skills/qa-diagram-generator/references/state-diagram.md +56 -0
- package/skills/qa-discovery-interview/SKILL.md +182 -0
- package/skills/qa-discovery-interview/references/completeness-checklist.md +53 -0
- package/skills/qa-discovery-interview/references/conflict-patterns.md +101 -0
- package/skills/qa-discovery-interview/references/qa-categories.md +147 -0
- package/skills/qa-discovery-interview/templates/qa-brief-template.md +168 -0
- package/skills/qa-environment-checker/SKILL.md +142 -0
- package/skills/qa-environment-checker/references/dependency-matrix.md +101 -0
- package/skills/qa-environment-checker/references/health-checks.md +209 -0
- package/skills/qa-environment-checker/templates/env-readiness-template.md +64 -0
- package/skills/qa-flaky-detector/SKILL.md +153 -0
- package/skills/qa-flaky-detector/references/ci-analysis.md +140 -0
- package/skills/qa-flaky-detector/references/flaky-patterns.md +247 -0
- package/skills/qa-github-issues-enhanced/SKILL.md +175 -0
- package/skills/qa-github-issues-enhanced/references/issue-templates.md +425 -0
- package/skills/qa-github-issues-enhanced/references/label-taxonomy.md +130 -0
- package/skills/qa-github-issues-enhanced/references/workflow-patterns.md +188 -0
- package/skills/qa-httpx-writer/SKILL.md +138 -0
- package/skills/qa-httpx-writer/references/assertions.md +195 -0
- package/skills/qa-httpx-writer/references/best-practices.md +140 -0
- package/skills/qa-httpx-writer/references/config.md +212 -0
- package/skills/qa-httpx-writer/references/patterns.md +262 -0
- package/skills/qa-jest-writer/SKILL.md +131 -0
- package/skills/qa-jest-writer/references/assertions.md +125 -0
- package/skills/qa-jest-writer/references/best-practices.md +136 -0
- package/skills/qa-jest-writer/references/config.md +134 -0
- package/skills/qa-jest-writer/references/patterns.md +172 -0
- package/skills/qa-jira-integration/SKILL.md +135 -0
- package/skills/qa-jira-integration/references/api-patterns.md +143 -0
- package/skills/qa-jira-integration/references/field-mapping.md +79 -0
- package/skills/qa-jira-integration/references/xray-integration.md +85 -0
- package/skills/qa-jmeter-writer/SKILL.md +171 -0
- package/skills/qa-jmeter-writer/references/best-practices.md +157 -0
- package/skills/qa-jmeter-writer/references/config.md +204 -0
- package/skills/qa-jmeter-writer/references/patterns.md +242 -0
- package/skills/qa-junit5-writer/SKILL.md +157 -0
- package/skills/qa-junit5-writer/references/assertions.md +118 -0
- package/skills/qa-junit5-writer/references/config.md +97 -0
- package/skills/qa-junit5-writer/references/patterns.md +162 -0
- package/skills/qa-k6-writer/SKILL.md +155 -0
- package/skills/qa-k6-writer/references/best-practices.md +236 -0
- package/skills/qa-k6-writer/references/config.md +219 -0
- package/skills/qa-k6-writer/references/patterns.md +304 -0
- package/skills/qa-linear-integration/SKILL.md +137 -0
- package/skills/qa-linear-integration/references/api-patterns.md +249 -0
- package/skills/qa-linear-integration/references/field-mapping.md +121 -0
- package/skills/qa-locust-writer/SKILL.md +151 -0
- package/skills/qa-locust-writer/references/best-practices.md +126 -0
- package/skills/qa-locust-writer/references/config.md +170 -0
- package/skills/qa-locust-writer/references/patterns.md +235 -0
- package/skills/qa-manual-test-designer/SKILL.md +145 -0
- package/skills/qa-manual-test-designer/references/exploratory-charters.md +138 -0
- package/skills/qa-manual-test-designer/references/personas.md +146 -0
- package/skills/qa-manual-test-designer/templates/exploratory-charter-template.md +47 -0
- package/skills/qa-manual-test-designer/templates/test-case-template.md +31 -0
- package/skills/qa-mobile-test-writer/SKILL.md +144 -0
- package/skills/qa-mobile-test-writer/references/best-practices.md +214 -0
- package/skills/qa-mobile-test-writer/references/config.md +309 -0
- package/skills/qa-mobile-test-writer/references/patterns.md +304 -0
- package/skills/qa-nfr-analyst/SKILL.md +177 -0
- package/skills/qa-nfr-analyst/references/iso-25010-model.md +159 -0
- package/skills/qa-nfr-analyst/references/owasp-wstg-baseline.md +202 -0
- package/skills/qa-nfr-analyst/references/wcag-checklist.md +184 -0
- package/skills/qa-nfr-analyst/templates/owasp-checklist-template.md +89 -0
- package/skills/qa-nfr-analyst/templates/wcag-checklist-template.md +48 -0
- package/skills/qa-orchestrator/SKILL.md +132 -0
- package/skills/qa-orchestrator/references/handoff-chains.md +105 -0
- package/skills/qa-orchestrator/references/pipeline-modes.md +115 -0
- package/skills/qa-orchestrator/references/scheduler-rules.md +84 -0
- package/skills/qa-pact-writer/SKILL.md +133 -0
- package/skills/qa-pact-writer/references/best-practices.md +100 -0
- package/skills/qa-pact-writer/references/config.md +135 -0
- package/skills/qa-pact-writer/references/patterns.md +161 -0
- package/skills/qa-plan-creator/SKILL.md +139 -0
- package/skills/qa-plan-creator/references/introduction-plan.md +43 -0
- package/skills/qa-plan-creator/references/migration-plan.md +44 -0
- package/skills/qa-plan-creator/references/onboarding-plan.md +46 -0
- package/skills/qa-plan-creator/references/performance-plan.md +44 -0
- package/skills/qa-plan-creator/references/regression-plan.md +45 -0
- package/skills/qa-plan-creator/references/release-plan.md +45 -0
- package/skills/qa-plan-creator/references/sprint-plan.md +44 -0
- package/skills/qa-plan-creator/references/test-plan.md +59 -0
- package/skills/qa-plan-creator/references/uat-plan.md +43 -0
- package/skills/qa-plan-creator/templates/checklist-template.md +36 -0
- package/skills/qa-plan-creator/templates/regression-checklist-template.md +49 -0
- package/skills/qa-plan-creator/templates/release-checklist-template.md +46 -0
- package/skills/qa-plan-creator/templates/test-plan-template.md +74 -0
- package/skills/qa-playwright-py-writer/SKILL.md +156 -0
- package/skills/qa-playwright-py-writer/references/best-practices.md +194 -0
- package/skills/qa-playwright-py-writer/references/config.md +195 -0
- package/skills/qa-playwright-py-writer/references/patterns.md +212 -0
- package/skills/qa-playwright-ts-writer/SKILL.md +151 -0
- package/skills/qa-playwright-ts-writer/references/assertions.md +109 -0
- package/skills/qa-playwright-ts-writer/references/best-practices.md +191 -0
- package/skills/qa-playwright-ts-writer/references/config.md +144 -0
- package/skills/qa-playwright-ts-writer/references/patterns.md +171 -0
- package/skills/qa-pytest-writer/SKILL.md +145 -0
- package/skills/qa-pytest-writer/references/assertions.md +149 -0
- package/skills/qa-pytest-writer/references/best-practices.md +97 -0
- package/skills/qa-pytest-writer/references/config.md +176 -0
- package/skills/qa-pytest-writer/references/patterns.md +251 -0
- package/skills/qa-qase-integration/SKILL.md +149 -0
- package/skills/qa-qase-integration/references/api-reference.md +354 -0
- package/skills/qa-qase-integration/references/ci-integration.md +196 -0
- package/skills/qa-qase-integration/references/field-mapping.md +157 -0
- package/skills/qa-requirements-generator/SKILL.md +152 -0
- package/skills/qa-requirements-generator/references/iso-29148-structure.md +153 -0
- package/skills/qa-requirements-generator/references/requirement-patterns.md +278 -0
- package/skills/qa-rest-assured-writer/SKILL.md +137 -0
- package/skills/qa-rest-assured-writer/references/best-practices.md +50 -0
- package/skills/qa-rest-assured-writer/references/config.md +124 -0
- package/skills/qa-rest-assured-writer/references/patterns.md +192 -0
- package/skills/qa-risk-analyzer/SKILL.md +158 -0
- package/skills/qa-risk-analyzer/references/impact-analysis.md +133 -0
- package/skills/qa-risk-analyzer/references/risk-factors.md +123 -0
- package/skills/qa-robot-framework-writer/SKILL.md +147 -0
- package/skills/qa-robot-framework-writer/references/best-practices.md +249 -0
- package/skills/qa-robot-framework-writer/references/config.md +204 -0
- package/skills/qa-robot-framework-writer/references/libraries.md +273 -0
- package/skills/qa-robot-framework-writer/references/patterns.md +216 -0
- package/skills/qa-security-test-writer/SKILL.md +123 -0
- package/skills/qa-security-test-writer/references/best-practices.md +155 -0
- package/skills/qa-security-test-writer/references/owasp-top10.md +331 -0
- package/skills/qa-security-test-writer/references/zap-config.md +258 -0
- package/skills/qa-selenium-java-writer/SKILL.md +143 -0
- package/skills/qa-selenium-java-writer/references/best-practices.md +59 -0
- package/skills/qa-selenium-java-writer/references/config.md +143 -0
- package/skills/qa-selenium-java-writer/references/patterns.md +170 -0
- package/skills/qa-selenium-py-writer/SKILL.md +150 -0
- package/skills/qa-selenium-py-writer/references/best-practices.md +175 -0
- package/skills/qa-selenium-py-writer/references/config.md +224 -0
- package/skills/qa-selenium-py-writer/references/patterns.md +255 -0
- package/skills/qa-shortcut-integration/SKILL.md +143 -0
- package/skills/qa-shortcut-integration/references/api-patterns.md +126 -0
- package/skills/qa-shortcut-integration/references/field-mapping.md +66 -0
- package/skills/qa-spec-auditor/SKILL.md +162 -0
- package/skills/qa-spec-auditor/references/audit-checklist.md +144 -0
- package/skills/qa-spec-auditor/references/drift-patterns.md +207 -0
- package/skills/qa-spec-writer/SKILL.md +143 -0
- package/skills/qa-spec-writer/references/gherkin-guide.md +253 -0
- package/skills/qa-spec-writer/references/specification-patterns.md +274 -0
- package/skills/qa-spring-test-writer/SKILL.md +170 -0
- package/skills/qa-spring-test-writer/references/best-practices.md +57 -0
- package/skills/qa-spring-test-writer/references/config.md +179 -0
- package/skills/qa-spring-test-writer/references/patterns.md +235 -0
- package/skills/qa-supertest-writer/SKILL.md +150 -0
- package/skills/qa-supertest-writer/references/assertions.md +192 -0
- package/skills/qa-supertest-writer/references/best-practices.md +102 -0
- package/skills/qa-supertest-writer/references/config.md +166 -0
- package/skills/qa-supertest-writer/references/patterns.md +242 -0
- package/skills/qa-task-creator/SKILL.md +142 -0
- package/skills/qa-task-creator/references/linking-patterns.md +127 -0
- package/skills/qa-task-creator/references/task-types.md +169 -0
- package/skills/qa-task-creator/templates/task-template.md +24 -0
- package/skills/qa-test-doc-compiler/SKILL.md +114 -0
- package/skills/qa-test-doc-compiler/references/agile-tailoring.md +220 -0
- package/skills/qa-test-doc-compiler/references/iso-29119-3-documents.md +302 -0
- package/skills/qa-test-healer/SKILL.md +101 -0
- package/skills/qa-test-healer/references/diagnosis-patterns.md +142 -0
- package/skills/qa-test-healer/references/fix-strategies.md +177 -0
- package/skills/qa-test-reporter/SKILL.md +130 -0
- package/skills/qa-test-reporter/references/best-practices.md +162 -0
- package/skills/qa-test-reporter/references/iso-29119-reports.md +236 -0
- package/skills/qa-test-reporter/references/report-formats.md +287 -0
- package/skills/qa-test-reviewer/SKILL.md +142 -0
- package/skills/qa-test-reviewer/references/anti-patterns.md +268 -0
- package/skills/qa-test-reviewer/references/review-checklist.md +93 -0
- package/skills/qa-test-strategy/SKILL.md +133 -0
- package/skills/qa-test-strategy/references/entry-exit-criteria.md +176 -0
- package/skills/qa-test-strategy/references/risk-matrix.md +102 -0
- package/skills/qa-test-strategy/references/testing-types.md +143 -0
- package/skills/qa-testcase-from-docs/SKILL.md +161 -0
- package/skills/qa-testcase-from-docs/references/test-case-format.md +196 -0
- package/skills/qa-testcase-from-docs/references/test-design-techniques.md +126 -0
- package/skills/qa-testcase-from-docs/templates/test-case-template.md +31 -0
- package/skills/qa-testcase-from-ui/SKILL.md +109 -0
- package/skills/qa-testcase-from-ui/references/ui-element-patterns.md +126 -0
- package/skills/qa-testcase-from-ui/references/visual-analysis-guide.md +146 -0
- package/skills/qa-testcase-from-ui/templates/test-case-template.md +31 -0
- package/skills/qa-visual-regression-writer/SKILL.md +175 -0
- package/skills/qa-visual-regression-writer/references/best-practices.md +154 -0
- package/skills/qa-visual-regression-writer/references/config.md +220 -0
- package/skills/qa-visual-regression-writer/references/patterns.md +213 -0
- package/skills/qa-vitest-writer/SKILL.md +141 -0
- package/skills/qa-vitest-writer/references/assertions.md +105 -0
- package/skills/qa-vitest-writer/references/best-practices.md +62 -0
- package/skills/qa-vitest-writer/references/config.md +127 -0
- package/skills/qa-vitest-writer/references/patterns.md +141 -0
- package/skills/qa-webdriverio-writer/SKILL.md +145 -0
- package/skills/qa-webdriverio-writer/references/best-practices.md +176 -0
- package/skills/qa-webdriverio-writer/references/config.md +240 -0
- package/skills/qa-webdriverio-writer/references/patterns.md +269 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# QA → Linear Field Mapping
|
|
2
|
+
|
|
3
|
+
*Mapping local QA fields (from qa-bug-ticket-creator, qa-task-creator) to Linear issue fields.*
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Bug Report → Linear Issue
|
|
8
|
+
|
|
9
|
+
| QA Bug Field | Linear Field | Notes |
|
|
10
|
+
| ------------ | ------------ | ----- |
|
|
11
|
+
| Title | `title` | Direct mapping; keep concise |
|
|
12
|
+
| Expected Result | `description` | In **Expected** section |
|
|
13
|
+
| Actual Result | `description` | In **Actual** section |
|
|
14
|
+
| Steps to Reproduce | `description` | In **Steps** section |
|
|
15
|
+
| Environment | `description` | In **Environment** section |
|
|
16
|
+
| Evidence | `description` | In **Evidence** section (code blocks) |
|
|
17
|
+
| Severity | `priority` + `labelIds` | See severity mapping below |
|
|
18
|
+
| Priority (P1–P5) | `priority` | See priority mapping below |
|
|
19
|
+
| Component/Module | `labelIds` | Map to Linear labels (e.g., `auth`, `frontend`) |
|
|
20
|
+
|
|
21
|
+
### Severity → Linear Priority
|
|
22
|
+
|
|
23
|
+
| QA Severity | Linear Priority |
|
|
24
|
+
| ----------- | --------------- |
|
|
25
|
+
| Blocker | 1 (Urgent) |
|
|
26
|
+
| Critical | 1 (Urgent) |
|
|
27
|
+
| Major | 2 (High) |
|
|
28
|
+
| Minor | 3 (Medium) |
|
|
29
|
+
| Trivial | 4 (Low) |
|
|
30
|
+
|
|
31
|
+
### Priority (P1–P5) → Linear Priority
|
|
32
|
+
|
|
33
|
+
| P1 | 1 (Urgent) |
|
|
34
|
+
| P2 | 2 (High) |
|
|
35
|
+
| P3 | 3 (Medium) |
|
|
36
|
+
| P4 | 4 (Low) |
|
|
37
|
+
| P5 | 4 (Low) |
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Task → Linear Issue
|
|
42
|
+
|
|
43
|
+
| QA Task Field | Linear Field | Notes |
|
|
44
|
+
| -------------- | ------------ | ----- |
|
|
45
|
+
| Title | `title` | Direct mapping |
|
|
46
|
+
| Description | `description` | Full context |
|
|
47
|
+
| Acceptance criteria | `description` | In **Acceptance Criteria** section |
|
|
48
|
+
| Task type | `labelIds` | `development`, `qa`, `documentation`, `enhancement` |
|
|
49
|
+
| Component | `labelIds` | Same as bug component labels |
|
|
50
|
+
| Links (bug, requirement) | `description` + relations | "Fixes BUG-123" in body; use `issueRelationCreate` for blocks |
|
|
51
|
+
| Parent bug | `parentId` or relation | Sub-task: `parentId`; fix task: "blocks" relation |
|
|
52
|
+
|
|
53
|
+
### Task Type → Linear Labels
|
|
54
|
+
|
|
55
|
+
| QA Task Type | Suggested Label |
|
|
56
|
+
| ------------ | --------------- |
|
|
57
|
+
| Development | `development` |
|
|
58
|
+
| QA | `qa` |
|
|
59
|
+
| Documentation | `documentation` |
|
|
60
|
+
| Enhancement | `enhancement` |
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Description Format (Markdown)
|
|
65
|
+
|
|
66
|
+
Use consistent structure for both bugs and tasks:
|
|
67
|
+
|
|
68
|
+
```markdown
|
|
69
|
+
## Expected
|
|
70
|
+
[Expected result]
|
|
71
|
+
|
|
72
|
+
## Actual
|
|
73
|
+
[Actual result]
|
|
74
|
+
|
|
75
|
+
## Steps to Reproduce
|
|
76
|
+
1. Step one
|
|
77
|
+
2. Step two
|
|
78
|
+
|
|
79
|
+
## Environment
|
|
80
|
+
- OS: ...
|
|
81
|
+
- Browser: ...
|
|
82
|
+
|
|
83
|
+
## Evidence
|
|
84
|
+
```
|
|
85
|
+
[Logs, stack trace]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Acceptance Criteria
|
|
89
|
+
- [ ] Criterion 1
|
|
90
|
+
- [ ] Criterion 2
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
For tasks, omit Expected/Actual/Steps when not applicable; include Acceptance Criteria.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Labels
|
|
98
|
+
|
|
99
|
+
Create or reuse labels in Linear for:
|
|
100
|
+
|
|
101
|
+
- **Component:** `auth`, `checkout`, `api`, `frontend`, `backend`
|
|
102
|
+
- **Type:** `bug`, `task`, `story`, `enhancement`
|
|
103
|
+
- **Source:** `qa`, `test-failure`, `coverage-gap`, `spec-audit`
|
|
104
|
+
|
|
105
|
+
Query existing labels:
|
|
106
|
+
|
|
107
|
+
```graphql
|
|
108
|
+
query { issueLabels { nodes { id name } } }
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Use `labelIds` (array of UUIDs) in issueCreate.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Team and Project
|
|
116
|
+
|
|
117
|
+
- **teamId** — Required for issue creation. Resolve from team key (e.g., `ENG`) via teams query.
|
|
118
|
+
- **projectId** — Optional; assign to project.
|
|
119
|
+
- **cycleId** — Optional; add to active cycle (sprint).
|
|
120
|
+
|
|
121
|
+
When user specifies "add to project X" or "add to cycle Y", query projects/cycles and use matching IDs.
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qa-locust-writer
|
|
3
|
+
description: Generate Locust performance tests in Python for load testing with distributed mode, custom load shapes, and real-time web UI monitoring.
|
|
4
|
+
output_dir: tests/performance
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# QA Locust Writer
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
Write Locust performance tests from test case specifications and performance plans. Transform structured test cases (from qa-testcase-from-docs, qa-manual-test-designer) and performance plans (from qa-plan-creator, qa-nfr-analyst) into executable Locust load tests with distributed mode, custom load shapes, real-time web UI, and event hooks.
|
|
12
|
+
|
|
13
|
+
## Trigger Phrases
|
|
14
|
+
|
|
15
|
+
- "Write Locust tests for [API/endpoint]"
|
|
16
|
+
- "Generate Locust load tests from performance plan"
|
|
17
|
+
- "Create Locust stress tests for [service]"
|
|
18
|
+
- "Add Locust tests with custom load shape"
|
|
19
|
+
- "Locust distributed load test for [URL]"
|
|
20
|
+
- "Python load tests with Locust"
|
|
21
|
+
- "Locust soak test for [endpoint]"
|
|
22
|
+
- "Spike test with Locust"
|
|
23
|
+
- "Locust tests with web UI"
|
|
24
|
+
|
|
25
|
+
## Key Features
|
|
26
|
+
|
|
27
|
+
| Feature | Description |
|
|
28
|
+
| ------- | ----------- |
|
|
29
|
+
| **HttpUser class** | Base class for HTTP-based load; `self.client` for requests |
|
|
30
|
+
| **TaskSets** | Group related tasks; nest for complex flows |
|
|
31
|
+
| **@task decorator** | Define user behaviors with optional weight |
|
|
32
|
+
| **wait_time** | `between`, `constant`, `constant_pacing` for think time |
|
|
33
|
+
| **Custom load shapes** | `LoadTestShape` for ramp, spike, soak, custom profiles |
|
|
34
|
+
| **Event hooks** | `events.request`, `events.init`, `events.test_start/stop` |
|
|
35
|
+
| **Distributed mode** | Master/worker for scaling across machines |
|
|
36
|
+
| **Real-time web UI** | Built-in dashboard at `http://localhost:8089` |
|
|
37
|
+
|
|
38
|
+
## Test Types
|
|
39
|
+
|
|
40
|
+
| Type | Description | Use Case |
|
|
41
|
+
| ---- | ----------- | -------- |
|
|
42
|
+
| **Load** | Steady load to verify baseline capacity | Baseline, capacity planning |
|
|
43
|
+
| **Stress** | Increase load until failure | Find breaking point |
|
|
44
|
+
| **Spike** | Sudden burst of traffic | Black Friday, flash sales |
|
|
45
|
+
| **Soak** | Sustained load over hours | Memory leaks, stability |
|
|
46
|
+
| **Custom shapes** | User-defined profile via LoadTestShape | Complex scenarios |
|
|
47
|
+
|
|
48
|
+
## Workflow
|
|
49
|
+
|
|
50
|
+
1. **Read performance plan** — From qa-plan-creator, qa-nfr-analyst, or test case specs
|
|
51
|
+
2. **Define user classes** — Create `HttpUser` subclasses per user type (e.g., `ApiUser`, `WebUser`)
|
|
52
|
+
3. **Set task weights** — Use `@task(weight=N)` for probability distribution
|
|
53
|
+
4. **Generate locustfile** — Produce `locustfile.py` with user classes, tasks, wait_time
|
|
54
|
+
5. **Configure** — Add `locust.conf` or CLI args; document distributed setup
|
|
55
|
+
|
|
56
|
+
## Context7 MCP
|
|
57
|
+
|
|
58
|
+
Use **Context7 MCP** for Locust documentation when:
|
|
59
|
+
- HttpUser, TaskSet, or LoadTestShape APIs need verification
|
|
60
|
+
- Event hooks or distributed mode options are uncertain
|
|
61
|
+
- wait_time, task weights, or configuration syntax require clarification
|
|
62
|
+
|
|
63
|
+
## Key Patterns
|
|
64
|
+
|
|
65
|
+
| Pattern | Usage |
|
|
66
|
+
| ------- | ----- |
|
|
67
|
+
| `class MyUser(HttpUser)` | Define user class; inherits `self.client` |
|
|
68
|
+
| `@task` / `@task(weight=3)` | Task method; weight = relative probability |
|
|
69
|
+
| `wait_time = between(1, 3)` | Random wait between tasks (seconds) |
|
|
70
|
+
| `wait_time = constant(2)` | Fixed wait |
|
|
71
|
+
| `wait_time = constant_pacing(1)` | Maintain ~1 req/sec per user |
|
|
72
|
+
| `self.client.get(url)` / `self.client.post(url)` | HTTP requests |
|
|
73
|
+
| `on_start` / `on_stop` | Setup/teardown per user instance |
|
|
74
|
+
| `LoadTestShape` | Custom load profile; override `tick()` |
|
|
75
|
+
| `events.request.add_listener` | Request-level hooks (success/failure) |
|
|
76
|
+
|
|
77
|
+
See `references/patterns.md` for user classes, task sets, load shapes, events, distributed.
|
|
78
|
+
|
|
79
|
+
## Distributed Setup
|
|
80
|
+
|
|
81
|
+
| Role | Command | Purpose |
|
|
82
|
+
| ---- | ------- | ------- |
|
|
83
|
+
| **Master** | `locust -f locustfile.py --master` | Coordinates workers, aggregates stats |
|
|
84
|
+
| **Worker** | `locust -f locustfile.py --worker --master-host=<master-ip>` | Runs load |
|
|
85
|
+
| **Expect workers** | `--expect-workers=4` | Master waits for N workers before starting |
|
|
86
|
+
|
|
87
|
+
## Configuration
|
|
88
|
+
|
|
89
|
+
- **CLI args** — `--host`, `--users`, `--spawn-rate`, `--run-time`, `--headless`
|
|
90
|
+
- **locust.conf** — Same options in config file
|
|
91
|
+
- **Environment variables** — `LOCUST_HOST`, `LOCUST_USERS`, etc.
|
|
92
|
+
|
|
93
|
+
See `references/config.md` for full configuration guide.
|
|
94
|
+
|
|
95
|
+
## File Naming
|
|
96
|
+
|
|
97
|
+
- `locustfile.py` — Default; or `locustfile_{service}.py` for multiple files
|
|
98
|
+
- `locust.conf` — Optional configuration
|
|
99
|
+
- Place in `tests/load/` or project root per convention
|
|
100
|
+
|
|
101
|
+
## Scope
|
|
102
|
+
|
|
103
|
+
**Can do (autonomous):**
|
|
104
|
+
- Generate Locust load tests from performance plans and test cases
|
|
105
|
+
- Define HttpUser classes, tasks, task weights, wait_time
|
|
106
|
+
- Implement LoadTestShape for load, stress, spike, soak profiles
|
|
107
|
+
- Add event hooks for request logging, custom metrics
|
|
108
|
+
- Document distributed setup (master/worker)
|
|
109
|
+
- Configure locust.conf, CLI args, env vars
|
|
110
|
+
- Use Context7 MCP for Locust docs
|
|
111
|
+
|
|
112
|
+
**Cannot do (requires confirmation):**
|
|
113
|
+
- Change production API implementation
|
|
114
|
+
- Add dependencies not in requirements.txt/pyproject.toml
|
|
115
|
+
- Override project config without approval
|
|
116
|
+
- Target production URLs without explicit request
|
|
117
|
+
|
|
118
|
+
**Will not do (out of scope):**
|
|
119
|
+
- Execute load tests (user runs `locust`)
|
|
120
|
+
- Write E2E browser tests (use qa-playwright-ts-writer)
|
|
121
|
+
- Modify CI/CD pipelines
|
|
122
|
+
- Bypass rate limits or ToS
|
|
123
|
+
|
|
124
|
+
## References
|
|
125
|
+
|
|
126
|
+
- `references/patterns.md` — User classes, task sets, load shapes, events, distributed
|
|
127
|
+
- `references/config.md` — CLI, locust.conf, environment variables, distributed setup
|
|
128
|
+
- `references/best-practices.md` — Realistic scenarios, correlation, custom shapes, CI integration
|
|
129
|
+
|
|
130
|
+
## Quality Checklist
|
|
131
|
+
|
|
132
|
+
- [ ] User classes match performance plan user types
|
|
133
|
+
- [ ] Task weights reflect realistic user behavior distribution
|
|
134
|
+
- [ ] wait_time is appropriate (avoid constant(0) unless intentional)
|
|
135
|
+
- [ ] No hardcoded secrets; use env vars for host, auth
|
|
136
|
+
- [ ] LoadTestShape tick() returns (user_count, spawn_rate) or None
|
|
137
|
+
- [ ] Event hooks do not block or slow down requests
|
|
138
|
+
- [ ] Distributed setup documented when scaling required
|
|
139
|
+
- [ ] Traceability to performance plan / NFR criteria
|
|
140
|
+
|
|
141
|
+
## Troubleshooting
|
|
142
|
+
|
|
143
|
+
| Symptom | Likely Cause | Fix |
|
|
144
|
+
| ------- | ------------ | --- |
|
|
145
|
+
| Connection refused | Wrong host or service down | Verify `--host`; ensure target is reachable |
|
|
146
|
+
| Low RPS despite many users | wait_time too high or blocking | Reduce wait_time; avoid sync I/O in tasks |
|
|
147
|
+
| Workers not connecting | Firewall, wrong master host | Check `--master-host`; open port 5557 |
|
|
148
|
+
| Memory growth in soak test | Leaks in app or test code | Profile app; avoid accumulating state in tasks |
|
|
149
|
+
| Inconsistent results | Shared state, non-determinism | Use per-user state; avoid global variables |
|
|
150
|
+
| Task distribution wrong | Incorrect weights | Verify @task(weight=N) sums; check task selection |
|
|
151
|
+
| Load shape not applied | LoadTestShape not used | Pass `--class-picker` or ensure shape in locustfile |
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Locust Best Practices
|
|
2
|
+
|
|
3
|
+
## Realistic Scenarios
|
|
4
|
+
|
|
5
|
+
### Match Production Traffic Mix
|
|
6
|
+
|
|
7
|
+
- **User mix:** Define multiple `HttpUser` classes with `weight` to reflect real user types (e.g., 80% readers, 20% writers).
|
|
8
|
+
- **Task distribution:** Use `@task(weight=N)` so high-frequency actions (e.g., browse) have higher weight than rare ones (e.g., checkout).
|
|
9
|
+
- **Think time:** Use `wait_time = between(1, 5)` or `constant_pacing` to avoid unrealistic burst patterns.
|
|
10
|
+
|
|
11
|
+
### Avoid Constant Zero Wait
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
# Avoid (unless intentional stress)
|
|
15
|
+
wait_time = constant(0) # Max RPS, no think time
|
|
16
|
+
|
|
17
|
+
# Prefer
|
|
18
|
+
wait_time = between(1, 3) # Simulates user think time
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Correlation and Session State
|
|
22
|
+
|
|
23
|
+
### Extract Dynamic Data from Responses
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
class ApiUser(HttpUser):
|
|
27
|
+
wait_time = between(1, 2)
|
|
28
|
+
|
|
29
|
+
@task
|
|
30
|
+
def create_and_get(self):
|
|
31
|
+
r = self.client.post("/api/items", json={"name": "test"})
|
|
32
|
+
if r.status_code == 201:
|
|
33
|
+
item_id = r.json()["id"]
|
|
34
|
+
self.client.get(f"/api/items/{item_id}")
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Use on_start for Auth
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
def on_start(self):
|
|
41
|
+
r = self.client.post("/auth/login", json={"user": "u", "pass": "p"})
|
|
42
|
+
self.token = r.json()["token"]
|
|
43
|
+
|
|
44
|
+
@task
|
|
45
|
+
def authenticated_request(self):
|
|
46
|
+
self.client.get("/api/secure", headers={"Authorization": f"Bearer {self.token}"})
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Avoid Global Mutable State
|
|
50
|
+
|
|
51
|
+
- Keep state per user instance (e.g., `self.token`).
|
|
52
|
+
- Do not use module-level variables that all users share; this can cause race conditions and skewed results.
|
|
53
|
+
|
|
54
|
+
## Custom Load Shapes
|
|
55
|
+
|
|
56
|
+
### Design for Test Type
|
|
57
|
+
|
|
58
|
+
| Test Type | Shape Pattern |
|
|
59
|
+
| --------- | ------------- |
|
|
60
|
+
| **Load** | Ramp up → sustain → optional ramp down |
|
|
61
|
+
| **Stress** | Gradual increase until failure |
|
|
62
|
+
| **Spike** | Low → sudden high → recovery |
|
|
63
|
+
| **Soak** | Ramp to target → hold for hours |
|
|
64
|
+
|
|
65
|
+
### Return Correct Tuple from tick()
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
def tick(self):
|
|
69
|
+
run_time = self.get_run_time()
|
|
70
|
+
# Return (user_count, spawn_rate) or None to stop
|
|
71
|
+
if run_time < 60:
|
|
72
|
+
return (50, 5)
|
|
73
|
+
return None
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## CI Integration
|
|
77
|
+
|
|
78
|
+
### Headless Execution
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
locust -f locustfile.py --host $TARGET_HOST --headless \
|
|
82
|
+
-u $USERS -r $SPAWN_RATE -t $DURATION \
|
|
83
|
+
--html report.html --csv results
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Exit Codes
|
|
87
|
+
|
|
88
|
+
- Locust exits 0 on success, non-zero on failure.
|
|
89
|
+
- Use `--run-time` to ensure tests complete; otherwise Ctrl+C is needed.
|
|
90
|
+
|
|
91
|
+
### Environment-Specific Hosts
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
# GitHub Actions example
|
|
95
|
+
- name: Run Locust
|
|
96
|
+
env:
|
|
97
|
+
LOCUST_HOST: ${{ secrets.STAGING_URL }}
|
|
98
|
+
LOCUST_USERS: 100
|
|
99
|
+
LOCUST_RUN_TIME: 5m
|
|
100
|
+
run: |
|
|
101
|
+
locust -f locustfile.py --headless
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Performance of the Test Itself
|
|
105
|
+
|
|
106
|
+
### Minimize Work in Tasks
|
|
107
|
+
|
|
108
|
+
- Avoid heavy computation, large allocations, or blocking I/O inside tasks.
|
|
109
|
+
- Use `self.client` (connection pooling) rather than creating new clients per request.
|
|
110
|
+
|
|
111
|
+
### Event Hooks
|
|
112
|
+
|
|
113
|
+
- Keep `events.request` listeners lightweight.
|
|
114
|
+
- Do not perform slow operations (e.g., DB writes) in listeners; use async or queue if needed.
|
|
115
|
+
|
|
116
|
+
## Security and Safety
|
|
117
|
+
|
|
118
|
+
- **No production by default:** Use staging/QA hosts unless explicitly requested.
|
|
119
|
+
- **Secrets:** Use environment variables for host, tokens, API keys.
|
|
120
|
+
- **Rate limits:** Respect target system limits; coordinate with team before large runs.
|
|
121
|
+
|
|
122
|
+
## Traceability
|
|
123
|
+
|
|
124
|
+
- Link load tests to performance plans (e.g., NFR IDs, plan section references).
|
|
125
|
+
- Document target SLAs (e.g., p95 < 500ms) in comments or a separate doc.
|
|
126
|
+
- Use consistent naming for user classes and tasks to align with plan scenarios.
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Locust Configuration
|
|
2
|
+
|
|
3
|
+
## CLI Arguments
|
|
4
|
+
|
|
5
|
+
### Common Options
|
|
6
|
+
|
|
7
|
+
| Option | Short | Description | Example |
|
|
8
|
+
| ------ | ----- | ----------- | ------- |
|
|
9
|
+
| `--host` | `-H` | Base URL for requests | `--host https://api.example.com` |
|
|
10
|
+
| `--users` | `-u` | Number of users to simulate | `--users 100` |
|
|
11
|
+
| `--spawn-rate` | `-r` | Users spawned per second | `--spawn-rate 10` |
|
|
12
|
+
| `--run-time` | `-t` | Test duration | `--run-time 5m` |
|
|
13
|
+
| `--headless` | | Run without web UI | `--headless` |
|
|
14
|
+
| `--locustfile` | `-f` | Path to locustfile | `-f locustfile.py` |
|
|
15
|
+
| `--web-host` | | Web UI bind address | `--web-host 0.0.0.0` |
|
|
16
|
+
| `--web-port` | | Web UI port | `--web-port 8089` |
|
|
17
|
+
|
|
18
|
+
### Distributed Options
|
|
19
|
+
|
|
20
|
+
| Option | Description |
|
|
21
|
+
| ------ | ----------- |
|
|
22
|
+
| `--master` | Run as master node |
|
|
23
|
+
| `--worker` | Run as worker node |
|
|
24
|
+
| `--master-host` | Master node hostname/IP |
|
|
25
|
+
| `--master-port` | Master port (default 5557) |
|
|
26
|
+
| `--expect-workers` | Master waits for N workers before starting |
|
|
27
|
+
|
|
28
|
+
### Example Commands
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Web UI mode
|
|
32
|
+
locust -f locustfile.py --host https://api.example.com
|
|
33
|
+
|
|
34
|
+
# Headless (CI)
|
|
35
|
+
locust -f locustfile.py --host https://api.example.com --headless -u 100 -r 10 -t 5m
|
|
36
|
+
|
|
37
|
+
# With custom user class
|
|
38
|
+
locust -f locustfile.py ApiUser --host https://api.example.com
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## locust.conf
|
|
42
|
+
|
|
43
|
+
Create `locust.conf` in project root or same directory as locustfile:
|
|
44
|
+
|
|
45
|
+
```ini
|
|
46
|
+
# locust.conf
|
|
47
|
+
locustfile = locustfile.py
|
|
48
|
+
host = https://api.example.com
|
|
49
|
+
|
|
50
|
+
# Web UI
|
|
51
|
+
web-host = 0.0.0.0
|
|
52
|
+
web-port = 8089
|
|
53
|
+
|
|
54
|
+
# Headless defaults
|
|
55
|
+
users = 100
|
|
56
|
+
spawn-rate = 10
|
|
57
|
+
run-time = 5m
|
|
58
|
+
headless = false
|
|
59
|
+
|
|
60
|
+
# Logging
|
|
61
|
+
loglevel = INFO
|
|
62
|
+
logfile = locust.log
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Using Config File
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
locust # Uses locust.conf in cwd
|
|
69
|
+
locust -f locustfile.py --config locust.conf
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
CLI args override config file values.
|
|
73
|
+
|
|
74
|
+
## Environment Variables
|
|
75
|
+
|
|
76
|
+
| Variable | Description |
|
|
77
|
+
| -------- | ----------- |
|
|
78
|
+
| `LOCUST_HOST` | Base URL (same as `--host`) |
|
|
79
|
+
| `LOCUST_LOCUSTFILE` | Path to locustfile |
|
|
80
|
+
| `LOCUST_USERS` | Number of users |
|
|
81
|
+
| `LOCUST_SPAWN_RATE` | Spawn rate |
|
|
82
|
+
| `LOCUST_RUN_TIME` | Run time (e.g., `5m`, `1h`) |
|
|
83
|
+
| `LOCUST_HEADLESS` | Set to `true` for headless |
|
|
84
|
+
| `LOCUST_WEB_HOST` | Web UI host |
|
|
85
|
+
| `LOCUST_WEB_PORT` | Web UI port |
|
|
86
|
+
|
|
87
|
+
### Example
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
export LOCUST_HOST=https://api.staging.example.com
|
|
91
|
+
export LOCUST_USERS=200
|
|
92
|
+
export LOCUST_SPAWN_RATE=20
|
|
93
|
+
export LOCUST_RUN_TIME=10m
|
|
94
|
+
locust -f locustfile.py --headless
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Distributed Setup
|
|
98
|
+
|
|
99
|
+
### Architecture
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
[Master] ---- port 5557 ---- [Worker 1]
|
|
103
|
+
| [Worker 2]
|
|
104
|
+
| [Worker 3]
|
|
105
|
+
+---- Web UI :8089 [Worker 4]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Master Configuration
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
locust -f locustfile.py \
|
|
112
|
+
--master \
|
|
113
|
+
--expect-workers=4 \
|
|
114
|
+
--host https://api.example.com \
|
|
115
|
+
--users 1000 \
|
|
116
|
+
--spawn-rate 50 \
|
|
117
|
+
--run-time 10m \
|
|
118
|
+
--headless
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Worker Configuration
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
locust -f locustfile.py \
|
|
125
|
+
--worker \
|
|
126
|
+
--master-host=192.168.1.100 \
|
|
127
|
+
--master-port=5557
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Docker Compose Example
|
|
131
|
+
|
|
132
|
+
```yaml
|
|
133
|
+
services:
|
|
134
|
+
master:
|
|
135
|
+
image: locustio/locust
|
|
136
|
+
command: -f /mnt/locustfile.py --master --expect-workers=4
|
|
137
|
+
ports:
|
|
138
|
+
- "8089:8089"
|
|
139
|
+
- "5557:5557"
|
|
140
|
+
volumes:
|
|
141
|
+
- ./locustfile.py:/mnt/locustfile.py
|
|
142
|
+
environment:
|
|
143
|
+
- LOCUST_HOST=https://api.example.com
|
|
144
|
+
|
|
145
|
+
worker:
|
|
146
|
+
image: locustio/locust
|
|
147
|
+
command: -f /mnt/locustfile.py --worker --master-host=master
|
|
148
|
+
volumes:
|
|
149
|
+
- ./locustfile.py:/mnt/locustfile.py
|
|
150
|
+
deploy:
|
|
151
|
+
replicas: 4
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Host in Code
|
|
155
|
+
|
|
156
|
+
Override host per user class or at runtime:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
class ApiUser(HttpUser):
|
|
160
|
+
host = "https://api.example.com" # Overrides --host for this class
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Or use environment:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
import os
|
|
167
|
+
|
|
168
|
+
class ApiUser(HttpUser):
|
|
169
|
+
host = os.environ.get("LOCUST_HOST", "http://localhost:8000")
|
|
170
|
+
```
|