ai-testing-swarm 0.1.11__tar.gz → 0.1.12__tar.gz

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.
Files changed (33) hide show
  1. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/PKG-INFO +1 -1
  2. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/pyproject.toml +1 -1
  3. ai_testing_swarm-0.1.12/src/ai_testing_swarm/__init__.py +1 -0
  4. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/agents/llm_reasoning_agent.py +36 -0
  5. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/agents/release_gate_agent.py +4 -1
  6. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/orchestrator.py +3 -0
  7. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm.egg-info/PKG-INFO +1 -1
  8. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm.egg-info/SOURCES.txt +1 -0
  9. ai_testing_swarm-0.1.12/tests/test_policy_expected_negatives.py +34 -0
  10. ai_testing_swarm-0.1.11/src/ai_testing_swarm/__init__.py +0 -1
  11. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/README.md +0 -0
  12. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/setup.cfg +0 -0
  13. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/agents/__init__.py +0 -0
  14. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/agents/execution_agent.py +0 -0
  15. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/agents/learning_agent.py +0 -0
  16. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/agents/test_planner_agent.py +0 -0
  17. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/agents/test_writer_agent.py +0 -0
  18. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/agents/ui_agent.py +0 -0
  19. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/cli.py +0 -0
  20. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/core/__init__.py +0 -0
  21. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/core/api_client.py +0 -0
  22. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/core/config.py +0 -0
  23. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/core/curl_parser.py +0 -0
  24. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/core/openai_client.py +0 -0
  25. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/core/openapi_loader.py +0 -0
  26. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/core/safety.py +0 -0
  27. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/reporting/__init__.py +0 -0
  28. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm/reporting/report_writer.py +0 -0
  29. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm.egg-info/dependency_links.txt +0 -0
  30. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm.egg-info/entry_points.txt +0 -0
  31. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/src/ai_testing_swarm.egg-info/top_level.txt +0 -0
  32. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/tests/test_openapi_loader.py +0 -0
  33. {ai_testing_swarm-0.1.11 → ai_testing_swarm-0.1.12}/tests/test_swarm_api.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ai-testing-swarm
3
- Version: 0.1.11
3
+ Version: 0.1.12
4
4
  Summary: AI-powered testing swarm
5
5
  Author-email: Arif Shah <ashah7775@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ai-testing-swarm"
7
- version = "0.1.11"
7
+ version = "0.1.12"
8
8
  description = "AI-powered testing swarm"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -0,0 +1 @@
1
+ __version__ = "0.1.12"
@@ -73,13 +73,33 @@ class LLMReasoningAgent:
73
73
  # =========================================================
74
74
  # 3️⃣ HTTP-LEVEL HARD RULES (NO AI)
75
75
  # =========================================================
76
+ # Method misuse tests: 404/405 are expected (endpoint not available for that method)
77
+ if status_code in (404, 405):
78
+ if (
79
+ isinstance(test_name, str)
80
+ and test_name.startswith("wrong_method_")
81
+ ) or (mutation and mutation.get("strategy") == "method_misuse"):
82
+ return {
83
+ "type": "method_not_allowed" if status_code == 405 else "not_found",
84
+ "confidence": 1.0,
85
+ "explanation": f"HTTP {status_code} for wrong-method negative test (expected)"
86
+ }
87
+
76
88
  if status_code == 405:
89
+ # 405 outside method-misuse tests can still be informative
77
90
  return {
78
91
  "type": "method_not_allowed",
79
92
  "confidence": 1.0,
80
93
  "explanation": "HTTP 405 Method Not Allowed"
81
94
  }
82
95
 
96
+ if status_code == 404:
97
+ return {
98
+ "type": "not_found",
99
+ "confidence": 0.9,
100
+ "explanation": "HTTP 404 Not Found"
101
+ }
102
+
83
103
  if status_code in (401, 403):
84
104
  return {
85
105
  "type": "auth_issue",
@@ -100,6 +120,22 @@ class LLMReasoningAgent:
100
120
  if mutation:
101
121
  strategy = mutation.get("strategy")
102
122
 
123
+ # Content negotiation / Accept header negative tests
124
+ if status_code == 406 and strategy == "headers":
125
+ return {
126
+ "type": "content_negotiation",
127
+ "confidence": 1.0,
128
+ "explanation": "406 Not Acceptable after Accept/header mutation (expected)"
129
+ }
130
+
131
+ # Wrong-method negative test accepted => risk
132
+ if 200 <= status_code < 300 and strategy == "method_misuse":
133
+ return {
134
+ "type": "method_risk",
135
+ "confidence": 1.0,
136
+ "explanation": "Wrong HTTP method was accepted with 2xx (unexpected)"
137
+ }
138
+
103
139
  if status_code == 400 and strategy == "missing_param":
104
140
  return {
105
141
  "type": "missing_param",
@@ -90,7 +90,7 @@ class ReleaseGateAgent:
90
90
  "infra", # infra / network / 5xx
91
91
  "security_risk", # malicious payload succeeded (2xx/3xx)
92
92
  "server_error",
93
- "method_not_allowed",
93
+ # NOTE: method_not_allowed is expected for negative tests (wrong method)
94
94
  }
95
95
 
96
96
  # ⚠️ Ambiguous behavior (release with caution)
@@ -104,6 +104,9 @@ class ReleaseGateAgent:
104
104
  "missing_param",
105
105
  "invalid_param",
106
106
  "security", # 🔥 IMPORTANT: security blocked = SAFE
107
+ "method_not_allowed",
108
+ "not_found",
109
+ "content_negotiation",
107
110
  }
108
111
 
109
112
  def decide(self, results: list) -> str:
@@ -14,6 +14,9 @@ EXPECTED_FAILURES = {
14
14
  "missing_param",
15
15
  "invalid_param",
16
16
  "security",
17
+ "method_not_allowed",
18
+ "not_found",
19
+ "content_negotiation",
17
20
  }
18
21
 
19
22
  class SwarmOrchestrator:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ai-testing-swarm
3
- Version: 0.1.11
3
+ Version: 0.1.12
4
4
  Summary: AI-powered testing swarm
5
5
  Author-email: Arif Shah <ashah7775@gmail.com>
6
6
  License: MIT
@@ -26,4 +26,5 @@ src/ai_testing_swarm/core/safety.py
26
26
  src/ai_testing_swarm/reporting/__init__.py
27
27
  src/ai_testing_swarm/reporting/report_writer.py
28
28
  tests/test_openapi_loader.py
29
+ tests/test_policy_expected_negatives.py
29
30
  tests/test_swarm_api.py
@@ -0,0 +1,34 @@
1
+ from ai_testing_swarm.agents.llm_reasoning_agent import LLMReasoningAgent
2
+ from ai_testing_swarm.agents.release_gate_agent import ReleaseGateAgent
3
+
4
+
5
+ def test_wrong_method_405_is_expected_not_blocking():
6
+ reasoner = LLMReasoningAgent()
7
+
8
+ exec_result = {
9
+ "name": "wrong_method_POST",
10
+ "mutation": {"strategy": "method_misuse"},
11
+ "response": {"status_code": 405, "elapsed_ms": 10, "body_snippet": ""},
12
+ }
13
+
14
+ cls = reasoner.reason(exec_result)
15
+ assert cls["type"] == "method_not_allowed"
16
+
17
+ # Gate should not reject release if happy path passes and only expected negatives exist
18
+ gate = ReleaseGateAgent()
19
+ decision = gate.decide([
20
+ {"name": "happy_path", "failure_type": "success", "response": {"status_code": 200}},
21
+ {"name": "wrong_method_POST", "failure_type": cls["type"], "response": {"status_code": 405}},
22
+ ])
23
+ assert decision in ("APPROVE_RELEASE", "APPROVE_RELEASE_WITH_RISKS")
24
+
25
+
26
+ def test_accept_header_406_is_expected():
27
+ reasoner = LLMReasoningAgent()
28
+ exec_result = {
29
+ "name": "headers_accept_text",
30
+ "mutation": {"strategy": "headers"},
31
+ "response": {"status_code": 406, "elapsed_ms": 10, "body_snippet": ""},
32
+ }
33
+ cls = reasoner.reason(exec_result)
34
+ assert cls["type"] == "content_negotiation"
@@ -1 +0,0 @@
1
- __version__ = "0.1.11"