decomposer: generate files for Create a production-suitable Dockerfile and minimal Docker Compose configuration for packaging and running the completed FastAPI endpoint monitoring service.
This commit is contained in:
61
tests/test_containerizer.py
Normal file
61
tests/test_containerizer.py
Normal file
@@ -0,0 +1,61 @@
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from containerizer import containerize
|
||||
|
||||
|
||||
class ContainerizerTests(unittest.TestCase):
|
||||
def service(self, health=True):
|
||||
temp = tempfile.TemporaryDirectory()
|
||||
root = Path(temp.name)
|
||||
(root / "app").mkdir()
|
||||
route = '@app.get("/health")\n' if health else ""
|
||||
(root / "app/main.py").write_text(
|
||||
"from fastapi import FastAPI\napp = FastAPI()\n" + route)
|
||||
(root / "requirements.lock").write_text("fastapi==0.115.6\nuvicorn==0.34.0\n")
|
||||
return temp, root
|
||||
|
||||
def payload(self, health="/health"):
|
||||
return {
|
||||
"service_specification": {"container": {
|
||||
"startup_module": "app.main:app", "port": 8000,
|
||||
"health_endpoint": health}},
|
||||
"target_management_implementation": {"preserved": 1},
|
||||
"endpoint_check_implementation": {"preserved": 2},
|
||||
"current_status_implementation": {"preserved": 3},
|
||||
}
|
||||
|
||||
def test_writes_artifacts_and_preserves_contract(self):
|
||||
temp, root = self.service()
|
||||
self.addCleanup(temp.cleanup)
|
||||
output = containerize(self.payload(), root)
|
||||
self.assertEqual(output["target_management_implementation"], {"preserved": 1})
|
||||
self.assertEqual(set(output["container_artifacts"]["files"]),
|
||||
{"Dockerfile", "compose.yaml", ".dockerignore"})
|
||||
self.assertIn("USER 10001:10001", (root / "Dockerfile").read_text())
|
||||
self.assertIn('uvicorn", "app.main:app', (root / "Dockerfile").read_text())
|
||||
self.assertIn("healthcheck:", (root / "compose.yaml").read_text())
|
||||
|
||||
def test_omits_healthcheck_without_matching_configuration(self):
|
||||
temp, root = self.service(health=False)
|
||||
self.addCleanup(temp.cleanup)
|
||||
containerize(self.payload(health=None), root)
|
||||
self.assertNotIn("healthcheck:", (root / "compose.yaml").read_text())
|
||||
|
||||
def test_rejects_healthcheck_not_present_in_app(self):
|
||||
temp, root = self.service(health=False)
|
||||
self.addCleanup(temp.cleanup)
|
||||
with self.assertRaisesRegex(ValueError, "not found"):
|
||||
containerize(self.payload(), root)
|
||||
|
||||
def test_rejects_unpinned_dependencies(self):
|
||||
temp, root = self.service()
|
||||
self.addCleanup(temp.cleanup)
|
||||
(root / "requirements.lock").write_text("fastapi>=0.100\n")
|
||||
with self.assertRaisesRegex(ValueError, "exact"):
|
||||
containerize(self.payload(), root)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user