Add mockapi source files and tests
This commit is contained in:
@@ -11,12 +11,7 @@ class DataGenerator:
|
|||||||
"""Generates realistic random test data from JSON schemas."""
|
"""Generates realistic random test data from JSON schemas."""
|
||||||
|
|
||||||
def __init__(self, seed: Optional[int] = None, schemas: Optional[Dict[str, Any]] = None):
|
def __init__(self, seed: Optional[int] = None, schemas: Optional[Dict[str, Any]] = None):
|
||||||
"""Initialize the data generator.
|
"""Initialize the data generator."""
|
||||||
|
|
||||||
Args:
|
|
||||||
seed: Random seed for reproducible data generation
|
|
||||||
schemas: Dictionary of schemas for $ref resolution
|
|
||||||
"""
|
|
||||||
self.seed = seed
|
self.seed = seed
|
||||||
self.faker = Faker()
|
self.faker = Faker()
|
||||||
if seed is not None:
|
if seed is not None:
|
||||||
@@ -46,8 +41,8 @@ class DataGenerator:
|
|||||||
"text": lambda: self.faker.text(),
|
"text": lambda: self.faker.text(),
|
||||||
"username": lambda: self.faker.user_name(),
|
"username": lambda: self.faker.user_name(),
|
||||||
"password": lambda: self.faker.password(),
|
"password": lambda: self.faker.password(),
|
||||||
"ip_v4": lambda: self.faker.ipv4(),
|
"ipv4": lambda: self.faker.ipv4(),
|
||||||
"ip_v6": lambda: self.faker.ipv6(),
|
"ipv6": lambda: self.faker.ipv6(),
|
||||||
"slug": lambda: self.faker.slug(),
|
"slug": lambda: self.faker.slug(),
|
||||||
"color": lambda: self.faker.color_name(),
|
"color": lambda: self.faker.color_name(),
|
||||||
"currency": lambda: self.faker.currency()[0],
|
"currency": lambda: self.faker.currency()[0],
|
||||||
@@ -55,14 +50,7 @@ class DataGenerator:
|
|||||||
}
|
}
|
||||||
|
|
||||||
def generate(self, schema: Dict[str, Any]) -> Any:
|
def generate(self, schema: Dict[str, Any]) -> Any:
|
||||||
"""Generate data from a JSON schema.
|
"""Generate data from a JSON schema."""
|
||||||
|
|
||||||
Args:
|
|
||||||
schema: JSON schema definition
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Generated data matching the schema
|
|
||||||
"""
|
|
||||||
if not schema or not isinstance(schema, dict):
|
if not schema or not isinstance(schema, dict):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -89,16 +77,8 @@ class DataGenerator:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def _resolve_ref(self, ref: str) -> Any:
|
def _resolve_ref(self, ref: str) -> Any:
|
||||||
"""Resolve a $ref reference.
|
"""Resolve a $ref reference."""
|
||||||
|
|
||||||
Args:
|
|
||||||
ref: Reference string like #/components/schemas/User
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Resolved schema or None
|
|
||||||
"""
|
|
||||||
parts = ref.lstrip("#/").split("/")
|
parts = ref.lstrip("#/").split("/")
|
||||||
|
|
||||||
skip_prefixes = ["components", "schemas"]
|
skip_prefixes = ["components", "schemas"]
|
||||||
start_idx = 0
|
start_idx = 0
|
||||||
for i, part in enumerate(parts):
|
for i, part in enumerate(parts):
|
||||||
@@ -106,23 +86,17 @@ class DataGenerator:
|
|||||||
start_idx = i + 1
|
start_idx = i + 1
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
parts = parts[start_idx:]
|
parts = parts[start_idx:]
|
||||||
|
|
||||||
if not parts:
|
if not parts:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
current = self._schemas_dict
|
current = self._schemas_dict
|
||||||
|
|
||||||
for part in parts:
|
for part in parts:
|
||||||
if isinstance(current, dict):
|
if isinstance(current, dict):
|
||||||
current = current.get(part, {})
|
current = current.get(part, {})
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if isinstance(current, dict):
|
if isinstance(current, dict):
|
||||||
return self.generate(current)
|
return self.generate(current)
|
||||||
|
|
||||||
return current
|
return current
|
||||||
|
|
||||||
def _generate_boolean(self, schema: Dict[str, Any]) -> bool:
|
def _generate_boolean(self, schema: Dict[str, Any]) -> bool:
|
||||||
@@ -135,7 +109,6 @@ class DataGenerator:
|
|||||||
"""Generate a random integer."""
|
"""Generate a random integer."""
|
||||||
if "enum" in schema:
|
if "enum" in schema:
|
||||||
return random.choice(schema["enum"])
|
return random.choice(schema["enum"])
|
||||||
|
|
||||||
minimum = schema.get("minimum", 0)
|
minimum = schema.get("minimum", 0)
|
||||||
maximum = schema.get("maximum", 10000)
|
maximum = schema.get("maximum", 10000)
|
||||||
return random.randint(int(minimum), int(maximum))
|
return random.randint(int(minimum), int(maximum))
|
||||||
@@ -144,7 +117,6 @@ class DataGenerator:
|
|||||||
"""Generate a random number."""
|
"""Generate a random number."""
|
||||||
if "enum" in schema:
|
if "enum" in schema:
|
||||||
return random.choice(schema["enum"])
|
return random.choice(schema["enum"])
|
||||||
|
|
||||||
minimum = schema.get("minimum", 0.0)
|
minimum = schema.get("minimum", 0.0)
|
||||||
maximum = schema.get("maximum", 10000.0)
|
maximum = schema.get("maximum", 10000.0)
|
||||||
return random.uniform(float(minimum), float(maximum))
|
return random.uniform(float(minimum), float(maximum))
|
||||||
@@ -153,46 +125,33 @@ class DataGenerator:
|
|||||||
"""Generate a random string."""
|
"""Generate a random string."""
|
||||||
if "enum" in schema:
|
if "enum" in schema:
|
||||||
return random.choice(schema["enum"])
|
return random.choice(schema["enum"])
|
||||||
|
|
||||||
format_type = schema.get("format", "")
|
format_type = schema.get("format", "")
|
||||||
|
|
||||||
if format_type in self._faker_providers:
|
if format_type in self._faker_providers:
|
||||||
return self._faker_providers[format_type]()
|
return self._faker_providers[format_type]()
|
||||||
|
|
||||||
if "pattern" in schema:
|
if "pattern" in schema:
|
||||||
return self._generate_by_pattern(schema["pattern"])
|
return self._generate_by_pattern(schema["pattern"])
|
||||||
|
|
||||||
min_length = schema.get("minLength", 1)
|
min_length = schema.get("minLength", 1)
|
||||||
max_length = schema.get("maxLength", 255)
|
max_length = schema.get("maxLength", 255)
|
||||||
|
|
||||||
return self.faker.text(max_nb_chars=random.randint(min_length, max_length))
|
return self.faker.text(max_nb_chars=random.randint(min_length, max_length))
|
||||||
|
|
||||||
def _generate_by_pattern(self, pattern: str) -> str:
|
def _generate_by_pattern(self, pattern: str) -> str:
|
||||||
"""Generate a string matching a regex pattern.
|
"""Generate a string matching a regex pattern."""
|
||||||
|
|
||||||
This is a simplified implementation.
|
|
||||||
"""
|
|
||||||
return self.faker.word()
|
return self.faker.word()
|
||||||
|
|
||||||
def _generate_array(self, schema: Dict[str, Any]) -> List[Any]:
|
def _generate_array(self, schema: Dict[str, Any]) -> List[Any]:
|
||||||
"""Generate a random array."""
|
"""Generate a random array."""
|
||||||
items = schema.get("items", {})
|
items = schema.get("items", {})
|
||||||
|
|
||||||
min_items = schema.get("minItems", 1)
|
min_items = schema.get("minItems", 1)
|
||||||
max_items = schema.get("maxItems", 10)
|
max_items = schema.get("maxItems", 10)
|
||||||
count = random.randint(int(min_items), int(max_items))
|
count = random.randint(int(min_items), int(max_items))
|
||||||
|
|
||||||
return [self.generate(items) for _ in range(count)]
|
return [self.generate(items) for _ in range(count)]
|
||||||
|
|
||||||
def _generate_object(self, schema: Dict[str, Any]) -> Dict[str, Any]:
|
def _generate_object(self, schema: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
"""Generate a random object."""
|
"""Generate a random object."""
|
||||||
properties = schema.get("properties", {})
|
properties = schema.get("properties", {})
|
||||||
|
|
||||||
result = {}
|
result = {}
|
||||||
|
|
||||||
for prop_name, prop_schema in properties.items():
|
for prop_name, prop_schema in properties.items():
|
||||||
result[prop_name] = self.generate(prop_schema)
|
result[prop_name] = self.generate(prop_schema)
|
||||||
|
|
||||||
additional_props = schema.get("additionalProperties")
|
additional_props = schema.get("additionalProperties")
|
||||||
if additional_props and isinstance(additional_props, dict):
|
if additional_props and isinstance(additional_props, dict):
|
||||||
min_props = schema.get("minProperties", 0)
|
min_props = schema.get("minProperties", 0)
|
||||||
@@ -200,5 +159,4 @@ class DataGenerator:
|
|||||||
count = random.randint(int(min_props), int(max_props))
|
count = random.randint(int(min_props), int(max_props))
|
||||||
for _ in range(count):
|
for _ in range(count):
|
||||||
result[self.faker.word()] = self.generate(additional_props)
|
result[self.faker.word()] = self.generate(additional_props)
|
||||||
|
return result
|
||||||
return result
|
|
||||||
|
|||||||
Reference in New Issue
Block a user