- TestBaseReader: abstract class - TestYamlReader: validate, parse, steps, requests, extracts, asserts - TestPostmanReader: validate, parse, nested items, headers, body - TestOpenAPIReader: validate, parse, step names, methods, paths, asserts - TestGetReader: auto-detection of formats
268 lines
8.3 KiB
Python
268 lines
8.3 KiB
Python
import pytest
|
|
from pathlib import Path
|
|
import tempfile
|
|
import os
|
|
|
|
from yamlreaders import YamlReader, PostmanReader, OpenAPIReader, get_reader
|
|
from yamlreaders.base import BaseReader, ParseError
|
|
|
|
|
|
TESTS_DIR = Path(__file__).parent
|
|
EXAMPLES_DIR = TESTS_DIR.parent / "examples"
|
|
|
|
|
|
class TestBaseReader:
|
|
def test_is_abstract(self):
|
|
with pytest.raises(TypeError):
|
|
BaseReader()
|
|
|
|
|
|
class TestYamlReader:
|
|
def test_validate_valid(self):
|
|
reader = YamlReader()
|
|
assert reader.validate(EXAMPLES_DIR / "custom.yaml") is True
|
|
|
|
def test_validate_invalid(self):
|
|
reader = YamlReader()
|
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
|
|
f.write("invalid: yaml\ncontent: here")
|
|
f.flush()
|
|
result = reader.validate(f.name)
|
|
os.unlink(f.name)
|
|
assert result is False
|
|
|
|
def test_parse(self):
|
|
reader = YamlReader()
|
|
model = reader.parse(EXAMPLES_DIR / "custom.yaml")
|
|
|
|
assert model.name == "Test Authorization"
|
|
assert model.base_url == "http://localhost:8080"
|
|
assert model.variables["email"] == "test@example.com"
|
|
assert model.variables["password"] == "Test123!"
|
|
assert len(model.steps) == 3
|
|
|
|
def test_parse_step_name(self):
|
|
reader = YamlReader()
|
|
model = reader.parse(EXAMPLES_DIR / "custom.yaml")
|
|
|
|
assert model.steps[0].name == "Register User"
|
|
assert model.steps[1].name == "Login"
|
|
assert model.steps[2].name == "Get Profile"
|
|
|
|
def test_parse_request(self):
|
|
reader = YamlReader()
|
|
model = reader.parse(EXAMPLES_DIR / "custom.yaml")
|
|
|
|
req = model.steps[0].request
|
|
assert req.method == "POST"
|
|
assert req.path == "/api/register"
|
|
assert req.headers["Content-Type"] == "application/json"
|
|
assert req.body["email"] == "{{email}}"
|
|
|
|
def test_parse_extract(self):
|
|
reader = YamlReader()
|
|
model = reader.parse(EXAMPLES_DIR / "custom.yaml")
|
|
|
|
extract = model.steps[0].extract
|
|
assert len(extract) == 1
|
|
assert extract[0].name == "user_id"
|
|
assert extract[0].json_path == "$.id"
|
|
|
|
def test_parse_assert(self):
|
|
reader = YamlReader()
|
|
model = reader.parse(EXAMPLES_DIR / "custom.yaml")
|
|
|
|
asserts = model.steps[0].assert_
|
|
assert len(asserts) == 1
|
|
assert asserts[0].type == "status"
|
|
assert asserts[0].value == 201
|
|
|
|
def test_parse_step_without_name_fails(self):
|
|
reader = YamlReader()
|
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
|
|
f.write("steps:\n - request:\n method: GET\n url: /")
|
|
f.flush()
|
|
with pytest.raises(ParseError):
|
|
reader.parse(f.name)
|
|
os.unlink(f.name)
|
|
|
|
def test_parse_step_without_request_fails(self):
|
|
reader = YamlReader()
|
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
|
|
f.write("steps:\n - name: Test")
|
|
f.flush()
|
|
with pytest.raises(ParseError):
|
|
reader.parse(f.name)
|
|
os.unlink(f.name)
|
|
|
|
|
|
class TestPostmanReader:
|
|
def test_validate_valid(self):
|
|
reader = PostmanReader()
|
|
assert reader.validate(EXAMPLES_DIR / "postman.yaml") is True
|
|
|
|
def test_parse(self):
|
|
reader = PostmanReader()
|
|
model = reader.parse(EXAMPLES_DIR / "postman.yaml")
|
|
|
|
assert model.name == "Test Collection"
|
|
assert model.base_url == "http://localhost:8080"
|
|
assert model.variables["email"] == "test@example.com"
|
|
assert len(model.steps) == 2
|
|
|
|
def test_parse_step_names(self):
|
|
reader = PostmanReader()
|
|
model = reader.parse(EXAMPLES_DIR / "postman.yaml")
|
|
|
|
assert model.steps[0].name == "Login"
|
|
assert model.steps[1].name == "Get Profile"
|
|
|
|
def test_parse_request_method(self):
|
|
reader = PostmanReader()
|
|
model = reader.parse(EXAMPLES_DIR / "postman.yaml")
|
|
|
|
assert model.steps[0].request.method == "POST"
|
|
assert model.steps[1].request.method == "GET"
|
|
|
|
def test_parse_request_headers(self):
|
|
reader = PostmanReader()
|
|
model = reader.parse(EXAMPLES_DIR / "postman.yaml")
|
|
|
|
headers = model.steps[0].request.headers
|
|
assert headers["Content-Type"] == "application/json"
|
|
|
|
def test_parse_request_body(self):
|
|
reader = PostmanReader()
|
|
model = reader.parse(EXAMPLES_DIR / "postman.yaml")
|
|
|
|
body = model.steps[0].request.body
|
|
assert body["email"] == "{{email}}"
|
|
assert body["password"] == "Test123!"
|
|
|
|
def test_parse_nested_items(self):
|
|
reader = PostmanReader()
|
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
|
|
f.write("""
|
|
info:
|
|
name: Nested
|
|
|
|
item:
|
|
- name: Folder
|
|
item:
|
|
- name: Nested Request
|
|
request:
|
|
method: GET
|
|
url: /nested
|
|
""")
|
|
f.flush()
|
|
model = reader.parse(f.name)
|
|
os.unlink(f.name)
|
|
|
|
assert len(model.steps) == 1
|
|
assert model.steps[0].name == "Nested Request"
|
|
|
|
def test_validate_invalid(self):
|
|
reader = PostmanReader()
|
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
|
|
f.write("info: {}\nother: data")
|
|
f.flush()
|
|
assert reader.validate(f.name) is False
|
|
os.unlink(f.name)
|
|
|
|
|
|
class TestOpenAPIReader:
|
|
def test_validate_valid(self):
|
|
reader = OpenAPIReader()
|
|
assert reader.validate(EXAMPLES_DIR / "openapi.yaml") is True
|
|
|
|
def test_parse(self):
|
|
reader = OpenAPIReader()
|
|
model = reader.parse(EXAMPLES_DIR / "openapi.yaml")
|
|
|
|
assert model.name == "Test API"
|
|
assert model.base_url == "http://localhost:8080"
|
|
assert len(model.steps) == 2
|
|
|
|
def test_parse_step_names(self):
|
|
reader = OpenAPIReader()
|
|
model = reader.parse(EXAMPLES_DIR / "openapi.yaml")
|
|
|
|
names = [s.name for s in model.steps]
|
|
assert "loginUser" in names
|
|
assert "getProfile" in names
|
|
|
|
def test_parse_request_methods(self):
|
|
reader = OpenAPIReader()
|
|
model = reader.parse(EXAMPLES_DIR / "openapi.yaml")
|
|
|
|
methods = [s.request.method for s in model.steps]
|
|
assert "POST" in methods
|
|
assert "GET" in methods
|
|
|
|
def test_parse_request_paths(self):
|
|
reader = OpenAPIReader()
|
|
model = reader.parse(EXAMPLES_DIR / "openapi.yaml")
|
|
|
|
paths = [s.request.path for s in model.steps]
|
|
assert "/api/login" in paths
|
|
assert "/api/profile" in paths
|
|
|
|
def test_parse_generates_asserts(self):
|
|
reader = OpenAPIReader()
|
|
model = reader.parse(EXAMPLES_DIR / "openapi.yaml")
|
|
|
|
for step in model.steps:
|
|
assert len(step.assert_) > 0
|
|
assert step.assert_[0].type == "status"
|
|
assert step.assert_[0].value == 200
|
|
|
|
def test_parse_with_servers(self):
|
|
reader = OpenAPIReader()
|
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
|
|
f.write("""
|
|
openapi: "3.0.0"
|
|
info:
|
|
title: Test
|
|
version: "1.0"
|
|
servers:
|
|
- url: https://api.example.com/v1
|
|
paths:
|
|
/test:
|
|
get:
|
|
operationId: test
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
""")
|
|
f.flush()
|
|
model = reader.parse(f.name)
|
|
os.unlink(f.name)
|
|
|
|
assert model.base_url == "https://api.example.com/v1"
|
|
|
|
def test_validate_invalid(self):
|
|
reader = OpenAPIReader()
|
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
|
|
f.write("swagger: '2.0'\ninfo:\n title: Test")
|
|
f.flush()
|
|
assert reader.validate(f.name) is False
|
|
os.unlink(f.name)
|
|
|
|
|
|
class TestGetReader:
|
|
def test_auto_detect_yaml(self):
|
|
reader = get_reader(EXAMPLES_DIR / "custom.yaml")
|
|
assert isinstance(reader, YamlReader)
|
|
|
|
def test_auto_detect_postman(self):
|
|
reader = get_reader(EXAMPLES_DIR / "postman.yaml")
|
|
assert isinstance(reader, PostmanReader)
|
|
|
|
def test_auto_detect_openapi(self):
|
|
reader = get_reader(EXAMPLES_DIR / "openapi.yaml")
|
|
assert isinstance(reader, OpenAPIReader)
|
|
|
|
def test_file_not_found(self):
|
|
with pytest.raises(FileNotFoundError):
|
|
get_reader("nonexistent.yaml")
|