From e9cfdd9e94219a0e431d272c486e2831653fcbda Mon Sep 17 00:00:00 2001 From: Kirill Date: Mon, 24 Aug 2026 16:46:52 +0300 Subject: [PATCH] test(models): Add comprehensive tests for all model classes - TestAuthModel: default values, credentials - TestRequestModel: default/custom values - TestExtractModel: values, header source - TestAssertModel: status/json asserts - TestStepModel: with request, extracts, asserts - TestTestModel: default values, full model - TestContext: resolve variables, extracted values - TestExtractor: body, nested, status, header extraction - TestValidator: status success/failure, empty asserts - TestExecutor: URL resolution with variables - TestStepResult: step result creation - TestTestResult: all passed, one failed, empty steps --- tests/test_models.py | 281 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 tests/test_models.py diff --git a/tests/test_models.py b/tests/test_models.py new file mode 100644 index 0000000..176db37 --- /dev/null +++ b/tests/test_models.py @@ -0,0 +1,281 @@ +import pytest +from models import ( + AuthModel, + RequestModel, + ExtractModel, + AssertModel, + StepModel, + TestModel, +) +from models.context import Context +from models.executor import Executor, Response +from models.extractor import Extractor +from models.validator import Validator +from models.runner import TestRunner, TestResult, StepResult + + +class TestAuthModel: + def test_default_values(self): + auth = AuthModel() + assert auth.type == "none" + assert auth.credentials == {} + + def test_with_credentials(self): + auth = AuthModel(type="bearer", credentials={"token": "abc123"}) + assert auth.type == "bearer" + assert auth.credentials["token"] == "abc123" + + +class TestRequestModel: + def test_default_values(self): + req = RequestModel() + assert req.method == "GET" + assert req.path == "/" + assert req.headers == {} + assert req.query == {} + assert req.body is None + assert req.body_type == "json" + assert req.timeout == 30 + + def test_custom_values(self): + req = RequestModel( + method="POST", + path="/api/users", + headers={"Content-Type": "application/json"}, + body={"name": "Test"}, + timeout=60, + ) + assert req.method == "POST" + assert req.path == "/api/users" + assert req.headers["Content-Type"] == "application/json" + assert req.body["name"] == "Test" + assert req.timeout == 60 + + +class TestExtractModel: + def test_values(self): + ext = ExtractModel(name="token", json_path="$.token") + assert ext.name == "token" + assert ext.json_path == "$.token" + assert ext.source == "body" + + def test_header_source(self): + ext = ExtractModel(name="auth", json_path="Authorization", source="header") + assert ext.source == "header" + + +class TestAssertModel: + def test_status_assert(self): + assertion = AssertModel(type="status", value=200) + assert assertion.type == "status" + assert assertion.value == 200 + + def test_json_assert(self): + assertion = AssertModel(type="json", path="$.id", operator="exists") + assert assertion.type == "json" + assert assertion.path == "$.id" + assert assertion.operator == "exists" + + +class TestStepModel: + def test_step_with_request(self): + step = StepModel( + name="Login", + request=RequestModel(method="POST", path="/login"), + ) + assert step.name == "Login" + assert step.request.method == "POST" + assert step.extract == [] + assert step.assert_ == [] + + def test_step_with_extracts_and_asserts(self): + step = StepModel( + name="Login", + request=RequestModel(method="POST", path="/login"), + extract=[ExtractModel(name="token", json_path="$.token")], + assert_=[AssertModel(type="status", value=200)], + ) + assert len(step.extract) == 1 + assert len(step.assert_) == 1 + + +class TestTestModel: + def test_default_values(self): + model = TestModel() + assert model.name == "Unnamed Test" + assert model.base_url == "" + assert model.variables == {} + assert model.auth is None + assert model.steps == [] + + def test_full_model(self): + model = TestModel( + name="API Test", + base_url="http://localhost:8080", + variables={"email": "test@x.com"}, + auth=AuthModel(type="bearer"), + steps=[ + StepModel( + name="Step1", + request=RequestModel(method="GET", path="/"), + ) + ], + ) + assert model.name == "API Test" + assert model.base_url == "http://localhost:8080" + assert model.variables["email"] == "test@x.com" + assert model.auth.type == "bearer" + assert len(model.steps) == 1 + + +class TestContext: + def test_resolve_simple(self): + model = TestModel(variables={"name": "Kirill"}) + ctx = Context(model) + assert ctx.resolve("Hello {{name}}") == "Hello Kirill" + + def test_resolve_extracted(self): + model = TestModel() + ctx = Context(model) + ctx.set_extracted("token", "abc123") + assert ctx.resolve("Bearer {{token}}") == "Bearer abc123" + + def test_resolve_multiple(self): + model = TestModel(variables={"host": "localhost"}) + ctx = Context(model) + ctx.set_extracted("port", "8080") + assert ctx.resolve("{{host}}:{{port}}") == "localhost:8080" + + def test_resolve_no_variable(self): + model = TestModel() + ctx = Context(model) + assert ctx.resolve("No variables here") == "No variables here" + + +class TestExtractor: + def test_extract_from_body(self): + model = TestModel() + ctx = Context(model) + extractor = Extractor(ctx) + + response = Response(status=200, body={"token": "abc123"}, headers={}) + configs = [ExtractModel(name="token", json_path="$.token")] + + extractor.extract(configs, response) + + assert ctx.extracted["token"] == "abc123" + + def test_extract_nested(self): + model = TestModel() + ctx = Context(model) + extractor = Extractor(ctx) + + response = Response( + status=200, + body={"user": {"id": 123, "name": "Test"}}, + headers={}, + ) + configs = [ExtractModel(name="user_id", json_path="$.user.id")] + + extractor.extract(configs, response) + + assert ctx.extracted["user_id"] == 123 + + def test_extract_from_status(self): + model = TestModel() + ctx = Context(model) + extractor = Extractor(ctx) + + response = Response(status=201, body={}, headers={}) + configs = [ExtractModel(name="status", json_path="status", source="status")] + + extractor.extract(configs, response) + + assert ctx.extracted["status"] == 201 + + def test_extract_from_header(self): + model = TestModel() + ctx = Context(model) + extractor = Extractor(ctx) + + response = Response(status=200, body={}, headers={"X-Request-Id": "req-123"}) + configs = [ExtractModel(name="req_id", json_path="X-Request-Id", source="header")] + + extractor.extract(configs, response) + + assert ctx.extracted["req_id"] == "req-123" + + +class TestValidator: + def test_validate_status_success(self): + validator = Validator() + response = Response(status=200, body={}, headers={}) + asserts = [AssertModel(type="status", value=200)] + + assert validator.validate(asserts, response) is True + + def test_validate_status_failure(self): + validator = Validator() + response = Response(status=404, body={}, headers={}) + asserts = [AssertModel(type="status", value=200)] + + assert validator.validate(asserts, response) is False + + def test_validate_empty_asserts(self): + validator = Validator() + response = Response(status=200, body={}, headers={}) + + assert validator.validate([], response) is True + + +class TestExecutor: + def test_resolve_url(self): + model = TestModel(base_url="http://localhost:8080") + ctx = Context(model) + executor = Executor(ctx) + + request = RequestModel(method="GET", path="/api/users") + assert executor._resolve_url(request) == "http://localhost:8080/api/users" + + def test_resolve_url_with_variables(self): + model = TestModel(base_url="http://localhost:8080") + ctx = Context(model) + ctx.set_extracted("user_id", "123") + executor = Executor(ctx) + + request = RequestModel(method="GET", path="/api/users/{{user_id}}") + assert executor._resolve_url(request) == "http://localhost:8080/api/users/123" + + +class TestStepResult: + def test_step_result(self): + response = Response(status=200, body={}, headers={}) + result = StepResult(name="Test", passed=True, response=response) + + assert result.name == "Test" + assert result.passed is True + assert result.response.status == 200 + + +class TestTestResult: + def test_all_passed(self): + response = Response(status=200, body={}, headers={}) + steps = [ + StepResult(name="S1", passed=True, response=response), + StepResult(name="S2", passed=True, response=response), + ] + result = TestResult(steps=steps) + assert result.passed is True + + def test_one_failed(self): + response = Response(status=200, body={}, headers={}) + steps = [ + StepResult(name="S1", passed=True, response=response), + StepResult(name="S2", passed=False, response=response), + ] + result = TestResult(steps=steps) + assert result.passed is False + + def test_empty_steps(self): + result = TestResult(steps=[]) + assert result.passed is True