Refactor Docker setup and add mock data support
- Updated .dockerignore and .gitignore for better file management. - Introduced .env.example for environment variable configuration. - Added docker-compose.dev.yml for development with mock data and live reload. - Enhanced Dockerfile to include necessary dependencies and entrypoint script. - Created mock_data.py to provide sample data for testing without OpenStack/Prometheus. - Added unit tests for template filters in dashboard. - Cleaned up various files for consistency and improved readability.
This commit is contained in:
1
dashboard/tests/__init__.py
Normal file
1
dashboard/tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Dashboard test package
|
||||
103
dashboard/tests/test_mathfilters.py
Normal file
103
dashboard/tests/test_mathfilters.py
Normal file
@@ -0,0 +1,103 @@
|
||||
"""Tests for dashboard.templatetags.mathfilters."""
|
||||
from django.test import TestCase
|
||||
from django.template import Template, Context
|
||||
|
||||
from dashboard.templatetags.mathfilters import div, mul, sub, convert_bytes
|
||||
|
||||
|
||||
class DivFilterTest(TestCase):
|
||||
"""Tests for the div template filter."""
|
||||
|
||||
def test_div_normal(self):
|
||||
self.assertEqual(div(10, 2), 5.0)
|
||||
self.assertEqual(div(10.0, 4), 2.5)
|
||||
|
||||
def test_div_by_zero(self):
|
||||
self.assertEqual(div(10, 0), 0)
|
||||
|
||||
def test_div_non_numeric(self):
|
||||
self.assertEqual(div("x", 2), 0)
|
||||
self.assertEqual(div(10, "y"), 0)
|
||||
self.assertEqual(div(None, 2), 0)
|
||||
|
||||
|
||||
class MulFilterTest(TestCase):
|
||||
"""Tests for the mul template filter."""
|
||||
|
||||
def test_mul_normal(self):
|
||||
self.assertEqual(mul(3, 4), 12.0)
|
||||
self.assertEqual(mul(2.5, 4), 10.0)
|
||||
|
||||
def test_mul_non_numeric(self):
|
||||
self.assertEqual(mul("a", 2), 0)
|
||||
self.assertEqual(mul(2, None), 0)
|
||||
|
||||
|
||||
class SubFilterTest(TestCase):
|
||||
"""Tests for the sub template filter."""
|
||||
|
||||
def test_sub_normal(self):
|
||||
self.assertEqual(sub(10, 3), 7.0)
|
||||
self.assertEqual(sub(5.5, 2), 3.5)
|
||||
|
||||
def test_sub_non_numeric(self):
|
||||
self.assertEqual(sub("x", 1), 0)
|
||||
self.assertEqual(sub(5, "y"), 0)
|
||||
|
||||
|
||||
class ConvertBytesFilterTest(TestCase):
|
||||
"""Tests for the convert_bytes template filter."""
|
||||
|
||||
def test_convert_to_B(self):
|
||||
self.assertEqual(convert_bytes(1024, "B"), 1024.0)
|
||||
|
||||
def test_convert_to_KB(self):
|
||||
self.assertEqual(convert_bytes(2048, "KB"), 2.0)
|
||||
|
||||
def test_convert_to_MB(self):
|
||||
self.assertEqual(convert_bytes(1024 * 1024 * 3, "MB"), 3.0)
|
||||
|
||||
def test_convert_to_GB(self):
|
||||
self.assertEqual(convert_bytes(1024 ** 3 * 5, "GB"), 5.0)
|
||||
|
||||
def test_convert_to_TB(self):
|
||||
self.assertEqual(convert_bytes(1024 ** 4, "TB"), 1.0)
|
||||
|
||||
def test_convert_default_GB(self):
|
||||
self.assertEqual(convert_bytes(1024 ** 3 * 2), 2.0)
|
||||
|
||||
def test_convert_invalid_unit_fallback_to_MB(self):
|
||||
self.assertEqual(convert_bytes(1024 * 1024, "invalid"), 1.0)
|
||||
self.assertEqual(convert_bytes(1024 * 1024, "xyz"), 1.0)
|
||||
|
||||
def test_convert_non_numeric_returns_zero(self):
|
||||
self.assertEqual(convert_bytes("abc"), 0.0)
|
||||
self.assertEqual(convert_bytes(None), 0.0)
|
||||
|
||||
def test_convert_rounds_to_one_decimal(self):
|
||||
self.assertEqual(convert_bytes(1500 * 1024 * 1024, "GB"), 1.5)
|
||||
self.assertEqual(convert_bytes(1536 * 1024 * 1024, "GB"), 1.5)
|
||||
|
||||
def test_convert_case_insensitive_unit(self):
|
||||
self.assertEqual(convert_bytes(1024 ** 3, "gb"), 1.0)
|
||||
self.assertEqual(convert_bytes(1024 ** 3, "GB"), 1.0)
|
||||
|
||||
|
||||
class MathfiltersTemplateIntegrationTest(TestCase):
|
||||
"""Test filters via template rendering."""
|
||||
|
||||
def test_div_in_template(self):
|
||||
t = Template("{% load mathfilters %}{{ a|div:b }}")
|
||||
self.assertEqual(t.render(Context({"a": 10, "b": 2})), "5.0")
|
||||
|
||||
def test_mul_in_template(self):
|
||||
t = Template("{% load mathfilters %}{{ a|mul:b }}")
|
||||
self.assertEqual(t.render(Context({"a": 3, "b": 4})), "12.0")
|
||||
|
||||
def test_sub_in_template(self):
|
||||
t = Template("{% load mathfilters %}{{ a|sub:b }}")
|
||||
self.assertEqual(t.render(Context({"a": 10, "b": 3})), "7.0")
|
||||
|
||||
def test_convert_bytes_in_template(self):
|
||||
t = Template("{% load mathfilters %}{{ bytes|convert_bytes:'GB' }}")
|
||||
self.assertEqual(t.render(Context({"bytes": 1024 ** 3 * 2})), "2.0")
|
||||
107
dashboard/tests/test_mock_data.py
Normal file
107
dashboard/tests/test_mock_data.py
Normal file
@@ -0,0 +1,107 @@
|
||||
"""Tests for dashboard.mock_data."""
|
||||
import json
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from dashboard.mock_data import get_mock_context
|
||||
|
||||
|
||||
class GetMockContextTest(TestCase):
|
||||
"""Tests for get_mock_context()."""
|
||||
|
||||
def test_returns_all_top_level_keys(self):
|
||||
ctx = get_mock_context()
|
||||
expected_keys = {"region", "pcpu", "vcpu", "pram", "vram", "vm", "flavors", "audits"}
|
||||
self.assertEqual(set(ctx.keys()), expected_keys)
|
||||
|
||||
def test_region_structure(self):
|
||||
ctx = get_mock_context()
|
||||
region = ctx["region"]
|
||||
self.assertIn("name", region)
|
||||
self.assertIn("hosts_total", region)
|
||||
self.assertEqual(region["name"], "mock-region")
|
||||
self.assertEqual(region["hosts_total"], 6)
|
||||
|
||||
def test_pcpu_structure_and_types(self):
|
||||
ctx = get_mock_context()
|
||||
pcpu = ctx["pcpu"]
|
||||
self.assertEqual(pcpu["total"], 48)
|
||||
self.assertEqual(pcpu["usage"], 12.5)
|
||||
self.assertEqual(pcpu["free"], 48 - 12.5)
|
||||
self.assertIsInstance(pcpu["used_percentage"], (int, float))
|
||||
|
||||
def test_vcpu_structure(self):
|
||||
ctx = get_mock_context()
|
||||
vcpu = ctx["vcpu"]
|
||||
self.assertIn("total", vcpu)
|
||||
self.assertIn("allocated", vcpu)
|
||||
self.assertIn("free", vcpu)
|
||||
self.assertIn("allocated_percentage", vcpu)
|
||||
self.assertIn("overcommit_ratio", vcpu)
|
||||
self.assertIn("overcommit_max", vcpu)
|
||||
self.assertEqual(vcpu["overcommit_max"], 2.0)
|
||||
|
||||
def test_pram_vram_structure(self):
|
||||
ctx = get_mock_context()
|
||||
pram = ctx["pram"]
|
||||
vram = ctx["vram"]
|
||||
self.assertIn("total", pram)
|
||||
self.assertIn("usage", pram)
|
||||
self.assertIn("free", pram)
|
||||
self.assertIn("used_percentage", pram)
|
||||
self.assertIn("total", vram)
|
||||
self.assertIn("allocated", vram)
|
||||
self.assertIn("overcommit_max", vram)
|
||||
|
||||
def test_vm_structure(self):
|
||||
ctx = get_mock_context()
|
||||
vm = ctx["vm"]
|
||||
self.assertEqual(vm["count"], 24)
|
||||
self.assertEqual(vm["active"], 22)
|
||||
self.assertEqual(vm["stopped"], 2)
|
||||
self.assertIn("avg_cpu", vm)
|
||||
self.assertIn("avg_ram", vm)
|
||||
self.assertIn("density", vm)
|
||||
|
||||
def test_flavors_structure(self):
|
||||
ctx = get_mock_context()
|
||||
flavors = ctx["flavors"]
|
||||
for key in ("first_common_flavor", "second_common_flavor", "third_common_flavor"):
|
||||
self.assertIn(key, flavors)
|
||||
self.assertIn("name", flavors[key])
|
||||
self.assertIn("count", flavors[key])
|
||||
self.assertEqual(flavors["first_common_flavor"]["name"], "m1.small")
|
||||
self.assertEqual(flavors["first_common_flavor"]["count"], 12)
|
||||
|
||||
def test_audits_serialized_fields(self):
|
||||
ctx = get_mock_context()
|
||||
self.assertIsInstance(ctx["audits"], list)
|
||||
self.assertGreaterEqual(len(ctx["audits"]), 1)
|
||||
for audit in ctx["audits"]:
|
||||
self.assertIn("migrations", audit)
|
||||
self.assertIn("host_labels", audit)
|
||||
self.assertIn("cpu_current", audit)
|
||||
self.assertIn("cpu_projected", audit)
|
||||
# These must be JSON strings (render-ready for JS)
|
||||
self.assertIsInstance(audit["migrations"], str)
|
||||
self.assertIsInstance(audit["host_labels"], str)
|
||||
self.assertIsInstance(audit["cpu_current"], str)
|
||||
self.assertIsInstance(audit["cpu_projected"], str)
|
||||
# Must be valid JSON
|
||||
json.loads(audit["migrations"])
|
||||
json.loads(audit["host_labels"])
|
||||
json.loads(audit["cpu_current"])
|
||||
json.loads(audit["cpu_projected"])
|
||||
|
||||
def test_audits_metadata_fields(self):
|
||||
ctx = get_mock_context()
|
||||
audit = ctx["audits"][0]
|
||||
self.assertIn("id", audit)
|
||||
self.assertIn("name", audit)
|
||||
self.assertIn("created_at", audit)
|
||||
self.assertIn("strategy", audit)
|
||||
self.assertIn("goal", audit)
|
||||
self.assertIn("type", audit)
|
||||
self.assertIn("scope", audit)
|
||||
self.assertIn("cpu_weight", audit)
|
||||
self.assertIn("ram_weight", audit)
|
||||
Reference in New Issue
Block a user