Skip to content

Commit

Permalink
[Refactor] Remove 'test statistics'
Browse files Browse the repository at this point in the history
  • Loading branch information
SchrodingersGat committed Nov 15, 2024
1 parent 7a3bed5 commit 3828149
Show file tree
Hide file tree
Showing 18 changed files with 1 addition and 555 deletions.
5 changes: 0 additions & 5 deletions src/backend/InvenTree/InvenTree/static/css/inventree.css
Original file line number Diff line number Diff line change
Expand Up @@ -1112,8 +1112,3 @@ a {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

.test-statistics-table-total-row {
font-weight: bold;
border-top-style: double;
}
2 changes: 0 additions & 2 deletions src/backend/InvenTree/InvenTree/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
from order.urls import order_urls
from part.urls import part_urls
from plugin.urls import get_plugin_urls
from stock.api import test_statistics_api_urls
from stock.urls import stock_urls
from web.urls import api_urls as web_api_urls
from web.urls import urlpatterns as platform_urls
Expand Down Expand Up @@ -110,7 +109,6 @@
),
]),
),
path('test-statistics/', include(test_statistics_api_urls)),
path('user/', include(users.api.user_urls)),
path('web/', include(web_api_urls)),
# Plugin endpoints
Expand Down
5 changes: 0 additions & 5 deletions src/backend/InvenTree/build/templates/build/build_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,6 @@ <h3>
});
});

{% if build.part.testable %}
onPanelLoad("test-statistics", function() {
prepareTestStatisticsTable('build', '{% url "api-test-statistics-by-build" build.pk %}')
});
{% endif %}
{% endif %}
{% endif %}

Expand Down
15 changes: 0 additions & 15 deletions src/backend/InvenTree/build/templates/build/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -267,21 +267,6 @@ <h4>
</div>
</div>

<div class='panel panel-hidden' id='panel-test-statistics'>
<div class='panel-heading'>
<h4>
{% trans "Build test statistics" %}
</h4>
</div>

<div class='panel-content'>
<div id='teststatistics-button-toolbar'>
{% include "filter_list.html" with id="buildteststatistics" %}
</div>
{% include "test_statistics_table.html" with prefix="build-" %}
</div>
</div>

<div class='panel panel-hidden' id='panel-attachments'>
<div class='panel-heading'>
<div class='d-flex flex-wrap'>
Expand Down
2 changes: 0 additions & 2 deletions src/backend/InvenTree/build/templates/build/sidebar.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
{% trans "Child Build Orders" as text %}
{% include "sidebar_item.html" with label='children' text=text icon="fa-sitemap" %}
{% if build.part.testable %}
{% trans "Test Statistics" as text %}
{% include "sidebar_item.html" with label='test-statistics' text=text icon="fa-chart-line" %}
{% endif %}
{% trans "Attachments" as text %}
{% include "sidebar_item.html" with label='attachments' text=text icon="fa-paperclip" %}
Expand Down
19 changes: 0 additions & 19 deletions src/backend/InvenTree/part/templates/part/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,22 +100,6 @@ <h4>{% trans "Part Test Templates" %}</h4>
</div>
</div>

<div class='panel panel-hidden' id='panel-test-statistics'>
<div class='panel-heading'>
<div class='d-flex flex-wrap'>
<h4>{% trans "Part Test Statistics" %}</h4>
{% include "spacer.html" %}
</div>
</div>
<div class='panel-content'>
<div id='teststatistics-button-toolbar'>
{% include "filter_list.html" with id="partteststatistics" %}
</div>

{% include "test_statistics_table.html" with prefix="part-" %}
</div>
</div>

<div class='panel panel-hidden' id='panel-purchase-orders'>
<div class='panel-heading'>
<div class='d-flex flex-wrap'>
Expand Down Expand Up @@ -767,9 +751,6 @@ <h4>{% trans "Part Manufacturers" %}</h4>
});
});
});
onPanelLoad("test-statistics", function() {
prepareTestStatisticsTable('part', '{% url "api-test-statistics-by-part" part.pk %}')
});

onPanelLoad("part-stock", function() {
$('#new-stock-item').click(function () {
Expand Down
2 changes: 0 additions & 2 deletions src/backend/InvenTree/part/templates/part/part_sidebar.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@
{% if part.testable %}
{% trans "Test Templates" as text %}
{% include "sidebar_item.html" with label="test-templates" text=text icon="fa-vial" %}
{% trans "Test Statistics" as text %}
{% include "sidebar_item.html" with label="test-statistics" text=text icon="fa-chart-line" %}
{% endif %}
{% if show_related %}
{% trans "Related Parts" as text %}
Expand Down
74 changes: 1 addition & 73 deletions src/backend/InvenTree/stock/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from django_filters import rest_framework as rest_filters
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema, extend_schema_field
from drf_spectacular.utils import extend_schema_field
from rest_framework import permissions, status
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
Expand Down Expand Up @@ -1241,54 +1241,6 @@ def filter_test_name(self, queryset, name, value):
return queryset.filter(template__key=key)


class TestStatisticsFilter(rest_filters.FilterSet):
"""API filter for the filtering the test results belonging to a specific build."""

class Meta:
"""Metaclass options."""

model = StockItemTestResult
fields = []

# Created date filters
finished_before = InvenTreeDateFilter(
label='Finished before', field_name='finished_datetime', lookup_expr='lte'
)
finished_after = InvenTreeDateFilter(
label='Finished after', field_name='finished_datetime', lookup_expr='gte'
)


class TestStatistics(GenericAPIView):
"""API endpoint for accessing a test statistics broken down by test templates."""

queryset = StockItemTestResult.objects.all()
serializer_class = StockSerializers.TestStatisticsSerializer
pagination_class = None
filterset_class = TestStatisticsFilter
filter_backends = SEARCH_ORDER_FILTER_ALIAS

@extend_schema(
responses={200: StockSerializers.TestStatisticsSerializer(many=False)}
)
def get(self, request, pk, *args, **kwargs):
"""Return test execution count matrix broken down by test result."""
instance = self.get_object()
serializer = self.get_serializer(instance)
if request.resolver_match.url_name == 'api-test-statistics-by-part':
serializer.context['type'] = 'by-part'
elif request.resolver_match.url_name == 'api-test-statistics-by-build':
serializer.context['type'] = 'by-build'
serializer.context['finished_datetime_after'] = self.request.query_params.get(
'finished_datetime_after'
)
serializer.context['finished_datetime_before'] = self.request.query_params.get(
'finished_datetime_before'
)
serializer.context['pk'] = pk
return Response([serializer.data])


class StockItemTestResultList(StockItemTestResultMixin, ListCreateDestroyAPIView):
"""API endpoint for listing (and creating) a StockItemTestResult object."""

Expand Down Expand Up @@ -1664,27 +1616,3 @@ def destroy(self, request, *args, **kwargs):
# Anything else
path('', StockList.as_view(), name='api-stock-list'),
]

test_statistics_api_urls = [
# Test statistics endpoints
path(
'by-part/',
include([
path(
'<int:pk>/',
TestStatistics.as_view(),
name='api-test-statistics-by-part',
)
]),
),
path(
'by-build/',
include([
path(
'<int:pk>/',
TestStatistics.as_view(),
name='api-test-statistics-by-build',
)
]),
),
]
63 changes: 0 additions & 63 deletions src/backend/InvenTree/stock/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import report.mixins
import report.models
import stock.tasks
from build import models as BuildModels
from common.icons import validate_icon
from common.settings import get_global_setting
from company import models as CompanyModels
Expand All @@ -48,7 +47,6 @@
)
from part import models as PartModels
from plugin.events import trigger_event
from stock import models as StockModels # noqa: PLW0406
from stock.generators import generate_batch_code
from users.models import Owner

Expand Down Expand Up @@ -2579,67 +2577,6 @@ def key(self):
"""Return key for test."""
return InvenTree.helpers.generateTestKey(self.test_name)

def calculate_test_statistics_for_test_template(
self, query_base, test_template, ret, start, end
):
"""Helper function to calculate the passed/failed/total tests count per test template type."""
query = query_base & Q(template=test_template.pk)
if start is not None and end is not None:
query = query & Q(started_datetime__range=(start, end))
elif start is not None and end is None:
query = query & Q(started_datetime__gt=start)
elif start is None and end is not None:
query = query & Q(started_datetime__lt=end)

passed = StockModels.StockItemTestResult.objects.filter(
query & Q(result=True)
).count()
failed = StockModels.StockItemTestResult.objects.filter(
query & ~Q(result=True)
).count()
if test_template.test_name not in ret:
ret[test_template.test_name] = {'passed': 0, 'failed': 0, 'total': 0}
ret[test_template.test_name]['passed'] += passed
ret[test_template.test_name]['failed'] += failed
ret[test_template.test_name]['total'] += passed + failed
ret['total']['passed'] += passed
ret['total']['failed'] += failed
ret['total']['total'] += passed + failed
return ret

def build_test_statistics(self, build_order_pk, start, end):
"""Generate a statistics matrix for each test template based on the test executions result counts."""
build = BuildModels.Build.objects.get(pk=build_order_pk)
if not build or not build.part.trackable:
return {}

test_templates = build.part.getTestTemplates()
ret = {'total': {'passed': 0, 'failed': 0, 'total': 0}}
for build_item in build.get_build_outputs():
for test_template in test_templates:
query_base = Q(stock_item=build_item)
ret = self.calculate_test_statistics_for_test_template(
query_base, test_template, ret, start, end
)
return ret

def part_test_statistics(self, part_pk, start, end):
"""Generate a statistics matrix for each test template based on the test executions result counts."""
part = PartModels.Part.objects.get(pk=part_pk)

if not part or not part.trackable:
return {}

test_templates = part.getTestTemplates()
ret = {'total': {'passed': 0, 'failed': 0, 'total': 0}}
for bo in part.stock_entries():
for test_template in test_templates:
query_base = Q(stock_item=bo)
ret = self.calculate_test_statistics_for_test_template(
query_base, test_template, ret, start, end
)
return ret

stock_item = models.ForeignKey(
StockItem, on_delete=models.CASCADE, related_name='test_results'
)
Expand Down
30 changes: 0 additions & 30 deletions src/backend/InvenTree/stock/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -904,36 +904,6 @@ def save(self):
item.uninstall_into_location(location, request.user, note)


class TestStatisticsLineField(serializers.DictField):
"""DRF field definition for one column of the test statistics."""

test_name = serializers.CharField()
results = serializers.DictField(child=serializers.IntegerField(min_value=0))


class TestStatisticsSerializer(serializers.Serializer):
"""DRF serializer class for the test statistics."""

results = serializers.ListField(child=TestStatisticsLineField(), read_only=True)

def to_representation(self, obj):
"""Just pass through the test statistics from the model."""
if self.context['type'] == 'by-part':
return obj.part_test_statistics(
self.context['pk'],
self.context['finished_datetime_after'],
self.context['finished_datetime_before'],
)
elif self.context['type'] == 'by-build':
return obj.build_test_statistics(
self.context['pk'],
self.context['finished_datetime_after'],
self.context['finished_datetime_before'],
)

raise ValidationError(_('Unsupported statistic type: ' + self.context['type']))


class ConvertStockItemSerializer(serializers.Serializer):
"""DRF serializer class for converting a StockItem to a valid variant part."""

Expand Down
35 changes: 0 additions & 35 deletions src/backend/InvenTree/stock/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2399,38 +2399,3 @@ def test_metadata(self):
'api-stock-item-metadata': StockItem,
}.items():
self.metatester(apikey, model)


class StockStatisticsTest(StockAPITestCase):
"""Tests for the StockStatistics API endpoints."""

fixtures = [*StockAPITestCase.fixtures, 'build']

def test_test_statistics(self):
"""Test the test statistics API endpoints."""
part = Part.objects.first()
response = self.get(
reverse('api-test-statistics-by-part', kwargs={'pk': part.pk}),
{},
expected_code=200,
)
self.assertEqual(response.data, [{}])

# Now trackable part
part1 = Part.objects.filter(trackable=True).first()
response = self.get(
reverse(
'api-test-statistics-by-part',
kwargs={'pk': part1.stock_items.first().pk},
),
{},
expected_code=404,
)
self.assertIn('detail', response.data)

# 105

bld = build.models.Build.objects.first()
url = reverse('api-test-statistics-by-build', kwargs={'pk': bld.pk})
response = self.get(url, {}, expected_code=200)
self.assertEqual(response.data, [{}])
Loading

0 comments on commit 3828149

Please sign in to comment.