sn-testing — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited sn-testing (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Before writing tests, evaluate each change with the 3 YES criteria — at least one must be met:
Do not write useless tests. Quality over quantity.
sn_mcp_server/tools/<feature>.py)SignNowAPIClient via MagicMock. Mock fastmcp.Context via AsyncMock when function accepts ctx.class TestFeatureName:
"""Test cases for _feature_function."""
@pytest.fixture
def mock_client(self):
"""Create a mock SignNowAPIClient."""
return MagicMock()
def test_feature_happy_path(self, mock_client):
"""Test successful execution with valid data."""
mock_client.api_method.return_value = SampleModel(...)
result = _feature_function(mock_client, "test_token", "param_value")
assert isinstance(result, ExpectedResponseModel)
assert result.field == "expected_value"
mock_client.api_method.assert_called_once_with("test_token", "param_value")sn_mcp_server/tools/models.py)from_* factories, status normalization, edge cases.class TestResponseModel:
"""Test cases for ResponseModel."""
def test_model_construction_with_defaults(self):
"""Test model handles missing optional fields."""
model = ResponseModel(id="test123", name="Test")
assert model.optional_field is None
@pytest.mark.parametrize("raw_status,expected", [
("sent", "pending"),
("fulfilled", "completed"),
])
def test_status_normalization(self, raw_status, expected):
"""Test raw API status maps to unified status."""
result = InviteStatusValues.from_raw_status(raw_status)
assert result == expectedsignnow_client/models/)by_alias=True), aliases, discriminators, coercion.class TestApiModel:
"""Test cases for API model validation."""
def test_model_from_api_payload(self):
"""Test model validates raw API JSON payload."""
payload = {"field_name": "value", "nested": {"key": "val"}}
model = ApiModel(**payload)
assert model.field_name == "value"
def test_model_serializes_with_alias(self):
"""Test model serializes using API-expected field names."""
model = RequestModel(from_="[email protected]")
dumped = model.model_dump(exclude_none=True, by_alias=True)
assert "from" in dumped
assert "from_" not in dumpedsignnow_client/client_*.py)_get/_post/_put to capture calls.class _DummyClient(DocumentClientMixin):
def __init__(self):
self.last_post = None
def _post(self, url, headers=None, data=None, json_data=None, validate_model=None):
self.last_post = {"url": url, "headers": headers, "json_data": json_data}
if validate_model:
return validate_model.model_validate({"status": "ok"})
return None
def test_client_method_passes_correct_url():
client = _DummyClient()
client.some_method(token="t", document_id="doc123")
assert client.last_post["url"] == "/document/doc123/some-endpoint"| Mock Target | Technique |
|---|---|
SignNowAPIClient | MagicMock() |
fastmcp.Context | AsyncMock(spec=Context) |
| API responses | Return real Pydantic model instances (not dicts) |
| API errors | side_effect with exception from signnow_client/exceptions.py |
Client internals (for client_*.py) | Dummy subclass overriding _get/_post |
SignNowAPIClient methods — never real HTTP calls.--asyncio-mode=auto in pytest.ini handles event loop automatically.
async def test_async_function(self, mock_client):
mock_context = AsyncMock(spec=Context)
mock_context.report_progress = AsyncMock()
result = await _async_feature(mock_context, "test_token", mock_client)
assert result is not Nonetests/unit/ mirroring source:src/sn_mcp_server/tools/<feature>.py → tests/unit/sn_mcp_server/tools/test_<feature>.pysrc/signnow_client/client_documents.py → tests/unit/signnow_client/test_client_documents.pytest_<module>.py. Classes: Test<Feature>. Methods: test_<what>_<scenario>.pytest.raises(ExceptionType, match=...), @pytest.mark.parametrize, fixtures over setUp/tearDown, raw assert."""Unit tests for <module> module."""pyproject.toml, pytest.ini, AGENTS.md).tools/signnow.py) — test business logic in tools/<feature>.py.Complete ALL before declaring done:
pytest tests/unit/ -v 2>&1 — must pass. If fails, fix and retry.ruff check tests/ 2>&1 — must pass.ruff format --check tests/ 2>&1 — must pass.Never declare "Done" until all pass.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.