refactor(itim): Serializer Unit Test Suite re-written to Pytest for model Service

ref: #932 #931
This commit is contained in:
2025-08-03 14:05:39 +09:30
parent 017f5de78a
commit 28cd56d9a0
8 changed files with 467 additions and 367 deletions

View File

@ -1,363 +0,0 @@
import pytest
from django.test import TestCase
from rest_framework.exceptions import ValidationError
from access.models.tenant import Tenant as Organization
from centurion.tests.abstract.mock_view import MockView, User
from itam.models.device import Device
from itim.models.services import Port
from itim.models.clusters import Cluster
from itim.serializers.service import Service, ServiceModelSerializer
class ServiceValidationAPI(
TestCase,
):
model = Service
@classmethod
def setUpTestData(self):
"""Setup Test
1. Create an org
2. Create an item
"""
organization = Organization.objects.create(name='test_org')
self.user = User.objects.create_user(username="test_user_view", password="password")
self.organization = organization
self.mock_view = MockView( user = self.user )
self.port = Port.objects.create(
organization = self.organization,
number = 80,
protocol = Port.Protocol.TCP
)
self.device = Device.objects.create(
organization = self.organization,
name = 'a-device'
)
self.cluster = Cluster.objects.create(
organization = self.organization,
name = 'a cluster'
)
self.item = self.model.objects.create(
organization=organization,
name = 'os name',
cluster = self.cluster,
config_key_variable = 'value'
)
self.item_two = self.model.objects.create(
organization=organization,
name = 'os name',
cluster = self.cluster,
)
self.item_two.dependent_service.set([ self.item ])
self.item_is_template = self.model.objects.create(
organization=organization,
name = 'os name',
is_template = True,
)
self.item_is_template.port.set([ self.port ])
self.item_is_template_no_port = self.model.objects.create(
organization=organization,
name = 'os name',
is_template = True,
)
def test_serializer_validation_can_create_device(self):
"""Serializer Validation Check
Ensure that a valid item is serialized
"""
serializer = ServiceModelSerializer(
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
'organization': self.organization.id,
'name': 'service',
'port': [
self.port.id
],
'config_key_variable': 'a_key',
'device': self.device.id
},
)
assert serializer.is_valid(raise_exception = True)
def test_serializer_validation_can_create_cluster(self):
"""Serializer Validation Check
Ensure that a valid item is serialized
"""
serializer = ServiceModelSerializer(
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
'organization': self.organization.id,
'name': 'service',
'port': [
self.port.id
],
'config_key_variable': 'a_key',
'cluster': self.cluster.id
},
)
assert serializer.is_valid(raise_exception = True)
def test_serializer_validation_no_name(self):
"""Serializer Validation Check
Ensure that if creating and no name is provided a validation error occurs
"""
with pytest.raises(ValidationError) as err:
serializer = ServiceModelSerializer(
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
'organization': self.organization.id,
'port': [
self.port.id
],
'config_key_variable': 'a_key',
'device': self.device.id
})
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['name'][0] == 'required'
def test_serializer_validation_no_port(self):
"""Serializer Validation Check
Ensure that if creating and no port is provided a validation error occurs
"""
with pytest.raises(ValidationError) as err:
serializer = ServiceModelSerializer(
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
'organization': self.organization.id,
'name': 'service',
'config_key_variable': 'a_key',
'device': self.device.id
})
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['port'][0] == 'required'
def test_serializer_validation_no_port_required_if_template_with_port(self):
"""Serializer Validation Check
Ensure that if creating and no port is provided and the template has a port
no validation error occurs
"""
serializer = ServiceModelSerializer(
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
'organization': self.organization.id,
'name': 'service',
'config_key_variable': 'a_key',
'device': self.device.id,
'template': self.item_is_template.id
})
assert serializer.is_valid(raise_exception = True)
def test_serializer_validation_template_without_port(self):
"""Serializer Validation Check
Ensure that if creating a port is provided and the template has no port
no validation error occurs
"""
serializer = ServiceModelSerializer(
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
'organization': self.organization.id,
'name': 'service',
'port': [
self.port.id
],
'config_key_variable': 'a_key',
'device': self.device.id,
'template': self.item_is_template_no_port.id
})
assert serializer.is_valid(raise_exception = True)
def test_serializer_validation_no_port_or_template_port(self):
"""Serializer Validation Check
Ensure that if creating and no port is provided and the template
has no port a validation error occurs
"""
with pytest.raises(ValidationError) as err:
serializer = ServiceModelSerializer(
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
'organization': self.organization.id,
'name': 'service',
'config_key_variable': 'a_key',
'device': self.device.id,
'template': self.item_is_template_no_port.id
})
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['port'][0] == 'required'
def test_serializer_validation_no_device(self):
"""Serializer Validation Check
Ensure that if creating and no device is provided a validation error occurs
"""
with pytest.raises(ValidationError) as err:
serializer = ServiceModelSerializer(
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
'organization': self.organization.id,
'name': 'service',
'port': [
self.port.id
],
'config_key_variable': 'a_key',
})
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['non_field_errors'][0] == 'one_of_cluster_or_device'
def test_serializer_validation_device_and_cluster(self):
"""Serializer Validation Check
Ensure that if creating and a cluster and device is provided
a validation error occurs
"""
with pytest.raises(ValidationError) as err:
serializer = ServiceModelSerializer(
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
'organization': self.organization.id,
'name': 'service',
'port': [
self.port.id
],
'config_key_variable': 'a_key',
'device': self.device.id,
'cluster': self.cluster.id
})
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['non_field_errors'][0] == 'either_cluster_or_device'
def test_serializer_validation_no_circular_dependency(self):
"""Serializer Validation Check
Ensure that if creating and a dependent service loop
a validation error occurs
"""
with pytest.raises(ValidationError) as err:
serializer = ServiceModelSerializer(
self.item,
context = {
'request': self.mock_view.request,
'view': self.mock_view,
},
data={
'dependent_service': [
self.item_two.id
],
},
partial = True
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['dependent_service'][0] == 'no_circular_dependencies'

View File

@ -17,3 +17,9 @@ def model_kwargs(request, kwargs_service):
if hasattr(request.cls, 'kwargs_create_item'):
del request.cls.kwargs_create_item
@pytest.fixture( scope = 'class')
def model_serializer(serializer_service):
yield serializer_service

View File

@ -0,0 +1,421 @@
import pytest
from django.db import models
from rest_framework.exceptions import ValidationError
from api.tests.unit.test_unit_serializer import (
SerializerTestCases
)
from centurion.tests.abstract.mock_view import MockView
@pytest.mark.model_service
class ServiceSerializerTestCases(
SerializerTestCases
):
@pytest.fixture( scope = 'function' )
def created_model(self, django_db_blocker, model, model_kwargs):
with django_db_blocker.unblock():
kwargs_many_to_many = {}
kwargs = {}
for key, value in model_kwargs.items():
field = model._meta.get_field(key)
if isinstance(field, models.ManyToManyField):
kwargs_many_to_many.update({
key: value
})
else:
kwargs.update({
key: value
})
item = model.objects.create( **kwargs )
for key, value in kwargs_many_to_many.items():
field = getattr(item, key)
for entry in value:
field.add(entry)
yield item
item.delete()
def test_serializer_validation_no_name(self,
kwargs_api_create, model, model_serializer, request_user
):
"""Serializer Validation Check
Ensure that if creating and no name is provided a validation error occurs
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = kwargs_api_create.copy()
del kwargs['name']
with pytest.raises(ValidationError) as err:
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs,
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['name'][0] == 'required'
def test_serializer_validation_can_create_device(self,
kwargs_api_create, model, model_serializer, request_user
):
"""Serializer Validation Check
Ensure that a valid item is serialized
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = kwargs_api_create.copy()
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs,
)
assert serializer.is_valid(raise_exception = True)
def test_serializer_validation_no_port(self,
kwargs_api_create, model, model_serializer, request_user
):
"""Serializer Validation Check
Ensure that if creating and no port is provided a validation error occurs
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = kwargs_api_create.copy()
del kwargs['port']
with pytest.raises(ValidationError) as err:
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs,
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['port'][0] == 'required'
def test_serializer_validation_no_port_required_if_template_with_port(self,
kwargs_api_create, model, model_serializer, request_user,
model_kwargs,
):
"""Serializer Validation Check
Ensure that if creating and no port is provided and the template has a port
no validation error occurs
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = model_kwargs
kwargs['is_template'] = True
ports = kwargs['port']
del kwargs['port']
template = model.objects.create( **kwargs )
for port in ports:
template.port.add( port )
kwargs = kwargs_api_create.copy()
kwargs['is_template'] = False
kwargs['template'] = template.id
del kwargs['port']
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs
)
assert serializer.is_valid(raise_exception = True)
template.delete()
def test_serializer_validation_template_without_port(self,
kwargs_api_create, model, model_serializer, request_user,
model_kwargs
):
"""Serializer Validation Check
Ensure that if creating a port is provided and the template has no port
no validation error occurs
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = model_kwargs
kwargs['is_template'] = True
del kwargs['port']
template = model.objects.create( **kwargs )
kwargs = kwargs_api_create.copy()
kwargs['is_template'] = False
kwargs['template'] = template.id
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs
)
assert serializer.is_valid(raise_exception = True)
template.delete()
def test_serializer_validation_no_port_or_template_port(self,
kwargs_api_create, model, model_serializer, request_user,
model_kwargs,
):
"""Serializer Validation Check
Ensure that if creating and no port is provided and the template
has no port a validation error occurs
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = model_kwargs
kwargs['is_template'] = True
del kwargs['port']
del kwargs['device']
template = model.objects.create( **kwargs )
kwargs = kwargs_api_create.copy()
kwargs['is_template'] = False
kwargs['template'] = template.id
del kwargs['port']
with pytest.raises(ValidationError) as err:
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['port'][0] == 'required'
template.delete()
def test_serializer_validation_no_device(self,
kwargs_api_create, model, model_serializer, request_user
):
"""Serializer Validation Check
Ensure that if creating and no device is provided a validation error occurs
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = kwargs_api_create.copy()
del kwargs['device']
with pytest.raises(ValidationError) as err:
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs,
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['non_field_errors'][0] == 'one_of_cluster_or_device'
def test_serializer_validation_device_and_cluster(self,
kwargs_api_create, model, model_serializer, request_user,
model_cluster, kwargs_cluster
):
"""Serializer Validation Check
Ensure that if creating and a cluster and device is provided
a validation error occurs
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = kwargs_cluster
nodes = kwargs['nodes']
del kwargs['nodes']
cluster = model_cluster.objects.create( **kwargs )
for node in nodes:
cluster.nodes.add( node )
kwargs = kwargs_api_create.copy()
kwargs['cluster'] = cluster.id
with pytest.raises(ValidationError) as err:
serializer = model_serializer['model'](
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['non_field_errors'][0] == 'either_cluster_or_device'
cluster.delete()
def test_serializer_validation_no_circular_dependency(self,
created_model,
kwargs_api_create, model, model_serializer, request_user,
model_kwargs
):
"""Serializer Validation Check
Ensure that if creating and a dependent service loop
a validation error occurs
"""
mock_view = MockView(
user = request_user,
model = model,
action = 'create',
)
kwargs = model_kwargs
del kwargs['port']
root_service = model.objects.create ( **kwargs )
root_service.dependent_service.add( created_model )
kwargs = kwargs_api_create.copy()
kwargs['dependent_service'] = [ root_service.id ]
with pytest.raises(ValidationError) as err:
serializer = model_serializer['model'](
created_model,
context = {
'request': mock_view.request,
'view': mock_view,
},
data = kwargs,
partial = True
)
serializer.is_valid(raise_exception = True)
assert err.value.get_codes()['dependent_service'][0] == 'no_circular_dependencies'
root_service.delete()
class ServiceSerializerInheritedCases(
ServiceSerializerTestCases
):
pass
@pytest.mark.module_itim
class ServiceSerializerPyTest(
ServiceSerializerTestCases
):
pass

View File

@ -267,6 +267,7 @@ from .model_role import (
from .model_service import (
kwargs_service,
model_service,
serializer_service,
)
from .model_slmticket import (

View File

@ -28,7 +28,11 @@ def kwargs_cluster(kwargs_centurionmodel, django_db_blocker,
with django_db_blocker.unblock():
node = model_device.objects.create( **kwargs_device )
kwargs = kwargs_device.copy()
kwargs['serial_number'] = 'clu-123-654'
kwargs['uuid'] = '1cf3a2d4-1776-418b-86eb-00404a43d60e'
node = model_device.objects.create( **kwargs )
cluster_type = model_clustertype.objects.create( **kwargs_clustertype )
kwargs = {

View File

@ -1,6 +1,8 @@
import pytest
import random
from django.db import models
from itam.models.device import Device
from itam.serializers.device import (
DeviceBaseSerializer,
@ -43,8 +45,15 @@ def kwargs_device(django_db_blocker, kwargs_centurionmodel,
with django_db_blocker.unblock():
device_model.delete()
device_type.delete()
try:
device_model.delete()
except models.deletion.ProtectedError:
pass
try:
device_type.delete()
except models.deletion.ProtectedError:
pass
@pytest.fixture( scope = 'class')

View File

@ -2,6 +2,8 @@ import datetime
import pytest
import random
from django.db import models
from itam.models.device import DeviceModel
from itam.serializers.device_model import (
DeviceModelBaseSerializer,
@ -41,7 +43,10 @@ def kwargs_devicemodel(kwargs_centurionmodel, django_db_blocker,
with django_db_blocker.unblock():
manufacturer.delete()
try:
manufacturer.delete()
except models.deletion.ProtectedError:
pass
@pytest.fixture( scope = 'class')

View File

@ -2,6 +2,11 @@ import datetime
import pytest
from itim.models.services import Service
from itim.serializers.service import (
ServiceBaseSerializer,
ServiceModelSerializer,
ServiceViewSerializer,
)
@ -39,6 +44,7 @@ def kwargs_service(django_db_blocker,
'device': device,
'config_key_variable': 'svc',
'port': [ port ],
'config': { 'config_key_1': 'config_value_1' }
}
yield kwargs.copy()
@ -51,3 +57,14 @@ def kwargs_service(django_db_blocker,
pass
port.delete()
@pytest.fixture( scope = 'class')
def serializer_service():
yield {
'base': ServiceBaseSerializer,
'model': ServiceModelSerializer,
'view': ServiceViewSerializer
}