Add AGENTS.md and document functional test conventions
Add an AGENTS.md routing index for AI coding agents, following the pattern established by Nova [1]. The TC discussion on the AGENTS.md community goal [2] concluded that projects should adopt AGENTS.md individually rather than as a mandated goal, so this adds one for openstacksdk. Rather than inlining rules in AGENTS.md, add a "Functional Tests" section to HACKING.rst documenting conventions that apply to both human and AI contributors: one test method per resource, _delete_foo cleanup helpers with addCleanup, failing on misconfigured environments instead of skipping, and testing both admin and non-admin personas. AGENTS.md then serves as a routing index pointing to HACKING.rst and other existing docs. [1] https://review.opendev.org/c/openstack/nova/+/984540 [2] https://review.opendev.org/c/openstack/governance/+/986765 Assisted-by: Claude claude-opus-4-6 claude-code-2.1.232 Change-Id: If01ebab65446ac02e6db698cc4819e7a8c5b40ef Signed-off-by: melanie witt <melwittt@gmail.com>
This commit is contained in:
1 parent
abfb363b78
commit
2819d1c912
2 files changed
+99
No files matched your search
@@ -0,0 +1,29 @@
|
||||
# AGENTS.md — agent routing index
|
||||
|
||||
Agents: explore the repo directly; this file is a routing index, not a
|
||||
contributor guide.
|
||||
|
||||
## Workflow
|
||||
|
||||
**For non-trivial planning**, inspect deps and tooling:
|
||||
`tox.ini` · `.pre-commit-config.yaml` ·
|
||||
`requirements.txt` · `test-requirements.txt`
|
||||
|
||||
**Tests**: Use `tox` or `stestr`; never use `pytest`.
|
||||
|
||||
**Routing:**
|
||||
- Style, hacking, checks: [HACKING.rst](HACKING.rst)
|
||||
- Unit test conventions: [HACKING.rst](HACKING.rst) (Unit Tests section)
|
||||
- Functional test conventions: [HACKING.rst](HACKING.rst) (Functional Tests section)
|
||||
- Contributing: [CONTRIBUTING.rst](CONTRIBUTING.rst)
|
||||
|
||||
## Guardrails
|
||||
|
||||
- **Tools:** Do not install missing tools with a package manager or `pip`.
|
||||
- **Review**: openstacksdk uses Gerrit, not GitHub PRs. Do not create
|
||||
pull requests.
|
||||
- **Commits**: Use the `Assisted-By:` trailer for AI-assisted contributions
|
||||
per the [OpenInfra AI policy](https://openinfra.org/legal/ai-policy).
|
||||
- **Git**: Read-only operations (`git log`, `git diff`, `git status`) are
|
||||
fine. Do not run mutating operations (`add`, `commit`, `reset`, `push`,
|
||||
etc.) unless explicitly instructed.
|
||||
+70
@@ -52,6 +52,76 @@ in a way that protects against local environment.
|
||||
Test cases should use requests-mock to mock out HTTP interactions rather than
|
||||
using mock to mock out object access.
|
||||
|
||||
Functional Tests
|
||||
-----------------
|
||||
|
||||
Functional tests run against a live devstack and are slow. Follow these
|
||||
conventions to keep them fast and reliable.
|
||||
|
||||
**One test method per resource.** Each test class should have a single
|
||||
``test_<resource>`` method that covers the full scenario for that resource
|
||||
(create, get, list, delete). Prerequisites go in ``setUp``; cleanup goes in
|
||||
``addCleanup``. This avoids redundant setUp/tearDown cycles and prevents a
|
||||
failure in one operation from causing knock-on failures in other test methods.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class TestFlavor(base.BaseFunctionalTest):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
# create prerequisites
|
||||
|
||||
def test_flavor(self):
|
||||
# create, get, list, update, delete
|
||||
|
||||
**Use _delete_foo helpers with addCleanup.** Move resource deletion into a
|
||||
``_delete_foo`` helper and register it via ``addCleanup`` immediately after
|
||||
creation. This ensures cleanup runs even if an assertion fails mid-test.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def _delete_flavor(self, flavor):
|
||||
ret = self.admin_compute_client.delete_flavor(flavor)
|
||||
self.assertIsNone(ret)
|
||||
|
||||
def test_flavor(self):
|
||||
flavor = self.admin_compute_client.create_flavor(...)
|
||||
self.addCleanup(self._delete_flavor, flavor)
|
||||
# ... remaining assertions
|
||||
|
||||
**Fail on misconfigured environments, don't skip.** Tests run against devstack,
|
||||
not production clouds. If a prerequisite is missing, fail with a descriptive
|
||||
message rather than silently skipping, so misconfigurations are caught
|
||||
immediately.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Wrong
|
||||
if not deployables:
|
||||
self.skipTest('No deployables found')
|
||||
|
||||
# Right
|
||||
self.assertGreater(
|
||||
len(deployables),
|
||||
0,
|
||||
'no deployables found: is the fake driver enabled?',
|
||||
)
|
||||
|
||||
**Test both personas where policy differs.** Use ``self.user_cloud`` for
|
||||
non-admin operations and ``self.operator_cloud`` for admin operations. Where
|
||||
services enforce different policy rules for admin vs non-admin, test both
|
||||
personas.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_device_profile(self):
|
||||
# get and list as regular user
|
||||
...
|
||||
|
||||
def test_device_profile_admin(self):
|
||||
# get, list, and delete as admin
|
||||
...
|
||||
|
||||
Don't Use setUpClass
|
||||
--------------------
|
||||
|
||||
|
||||
Reference in new issue
Block a user