Files
OperatorSchedule/tests/test_models.py

354 lines
14 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
test_models.py - Тесты для моделей и предпочтений
Проверяют корректность работы класса OperatorPreferences и связанных функций
"""
import pytest
from datetime import datetime
from models import (
OperatorPreferences,
PreferencesBuilder,
DayOfWeek,
PreferenceType,
get_days,
create_model,
solve_model,
get_solution
)
from config import YEAR, MONTH, SHIFTS, OPERATORS
class TestDayOfWeek:
"""Тесты для enum DayOfWeek"""
def test_day_of_week_values(self):
"""Проверка значений enum"""
assert DayOfWeek.MONDAY.value == 0
assert DayOfWeek.TUESDAY.value == 1
assert DayOfWeek.WEDNESDAY.value == 2
assert DayOfWeek.THURSDAY.value == 3
assert DayOfWeek.FRIDAY.value == 4
assert DayOfWeek.SATURDAY.value == 5
assert DayOfWeek.SUNDAY.value == 6
def test_day_of_week_names(self):
"""Проверка названий enum"""
assert DayOfWeek.MONDAY.name == "MONDAY"
assert DayOfWeek.SUNDAY.name == "SUNDAY"
class TestOperatorPreferences:
"""Тесты для класса OperatorPreferences"""
def test_creation(self):
"""Тест создания объекта предпочтений"""
prefs = OperatorPreferences("Тестовый")
assert prefs.operator_name == "Тестовый"
assert prefs.work_on_dates == []
assert prefs.work_on_day_of_week == []
assert prefs.work_only_shift is None
assert prefs.off_on_dates == []
def test_to_dict_empty(self):
"""Тест конвертации в словарь для пустых предпочтений"""
prefs = OperatorPreferences("Тестовый")
result = prefs.to_dict()
assert result == {}
def test_to_dict_with_dates(self):
"""Тест конвертации с датами"""
prefs = OperatorPreferences("Тестовый")
prefs.work_on_dates = [10, 15, 20]
result = prefs.to_dict()
assert result['dates'] == [10, 15, 20]
def test_to_dict_with_shift(self):
"""Тест конвертации со сменой"""
prefs = OperatorPreferences("Тестовый")
prefs.work_only_shift = 2
result = prefs.to_dict()
assert result['shift'] == 2
def test_to_dict_with_day_of_week(self):
"""Тест конвертации с днем недели"""
prefs = OperatorPreferences("Тестовый")
prefs.work_on_day_of_week = [DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY]
result = prefs.to_dict()
assert result['day_of_week'] == ['monday', 'wednesday']
def test_to_dict_with_off_dates(self):
"""Тест конвертации с днями отдыха"""
prefs = OperatorPreferences("Тестовый")
prefs.off_on_dates = [5, 12, 19]
result = prefs.to_dict()
assert result['off_dates'] == [5, 12, 19]
def test_to_dict_all(self):
"""Тест конвертации всех полей"""
prefs = OperatorPreferences("Тестовый")
prefs.work_on_dates = [10, 15]
prefs.work_on_day_of_week = [DayOfWeek.MONDAY]
prefs.work_only_shift = 1
prefs.off_on_dates = [5]
result = prefs.to_dict()
assert result['dates'] == [10, 15]
assert result['day_of_week'] == ['monday']
assert result['shift'] == 1
assert result['off_dates'] == [5]
def test_from_dict(self):
"""Тест создания из словаря"""
data = {
'dates': [10, 15],
'day_of_week': ['monday'],
'shift': 1,
'off_dates': [5]
}
prefs = OperatorPreferences.from_dict("Тестовый", data)
assert prefs.work_on_dates == [10, 15]
assert prefs.work_on_day_of_week == [DayOfWeek.MONDAY]
assert prefs.work_only_shift == 1
assert prefs.off_on_dates == [5]
def test_from_dict_partial(self):
"""Тест создания из словаря с неполными данными"""
data = {'dates': [10]}
prefs = OperatorPreferences.from_dict("Тестовый", data)
assert prefs.work_on_dates == [10]
assert prefs.work_on_day_of_week == []
assert prefs.work_only_shift is None
assert prefs.off_on_dates == []
def test_from_dict_invalid_day_of_week(self):
"""Тест обработки невалидного дня недели"""
data = {'day_of_week': ['invalid']}
prefs = OperatorPreferences.from_dict("Тестовый", data)
assert prefs.work_on_day_of_week == []
def test_from_dict_invalid_shift(self):
"""Тест обработки невалидной смены"""
data = {'shift': 5}
prefs = OperatorPreferences.from_dict("Тестовый", data)
assert prefs.work_only_shift is None
def test_from_dict_invalid_dates(self):
"""Тест обработки невалидных дат"""
data = {'dates': [32]}
prefs = OperatorPreferences.from_dict("Тестовый", data)
assert prefs.work_on_dates == []
def test_from_dict_invalid_off_dates(self):
"""Тест обработки невалидных дней отдыха"""
data = {'off_dates': [32]}
prefs = OperatorPreferences.from_dict("Тестовый", data)
assert prefs.off_on_dates == []
class TestPreferencesBuilder:
"""Тесты для класса PreferencesBuilder"""
def test_creation(self):
"""Тест создания объекта"""
builder = PreferencesBuilder("Тестовый")
assert builder.operator_name == "Тестовый"
assert builder._preferences is None
def test_add_dates(self):
"""Тест добавления дат"""
builder = PreferencesBuilder("Тестовый")
builder.add_dates([10, 15])
assert builder._preferences.work_on_dates == [10, 15]
def test_add_day_of_week(self):
"""Тест добавления дней недели"""
builder = PreferencesBuilder("Тестовый")
builder.add_day_of_week([DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY])
assert len(builder._preferences.work_on_day_of_week) == 2
def test_add_shift(self):
"""Тест добавления смены"""
builder = PreferencesBuilder("Тестовый")
builder.add_shift(2)
assert builder._preferences.work_only_shift == 2
def test_add_off_dates(self):
"""Тест добавления дней отдыха"""
builder = PreferencesBuilder("Тестовый")
builder.add_off_dates([5, 12])
assert builder._preferences.off_on_dates == [5, 12]
def test_to_dict(self):
"""Тест конвертации в словарь"""
builder = PreferencesBuilder("Тестовый")
builder.add_dates([10])
builder.add_shift(1)
result = builder.to_dict()
assert result['dates'] == [10]
assert result['shift'] == 1
def test_to_dict_empty(self):
"""Тест конвертации пустых предпочтений"""
builder = PreferencesBuilder("Тестовый")
result = builder.to_dict()
assert result == {}
def test_to_dict_invalid(self):
"""Тест обработки невалидных данных"""
builder = PreferencesBuilder("Тестовый")
builder.add_dates([32]) # Невалидная дата
result = builder.to_dict()
assert result == {}
def test_to_dict_invalid_day_of_week(self):
"""Тест обработки невалидного дня недели"""
builder = PreferencesBuilder("Тестовый")
builder.add_day_of_week([DayOfWeek.MONDAY, "invalid"])
result = builder.to_dict()
assert result['day_of_week'] == ['monday']
def test_to_dict_invalid_shift(self):
"""Тест обработки невалидной смены"""
builder = PreferencesBuilder("Тестовый")
builder.add_shift(5) # Невалидная смена
result = builder.to_dict()
assert result == {}
def test_to_dict_invalid_off_dates(self):
"""Тест обработки невалидных дней отдыха"""
builder = PreferencesBuilder("Тестовый")
builder.add_off_dates([32]) # Невалидная дата
result = builder.to_dict()
assert result == {}
class TestGetDays:
"""Тесты для функции get_days"""
def test_days_count(self):
"""Проверка количества дней"""
days = get_days()
assert len(days) == 30 # Апрель 2026
def test_days_format(self):
"""Проверка формата дней"""
days = get_days()
for day in days:
assert isinstance(day, str)
assert len(day) == 10 # YYYY-MM-DD
assert '-' in day
def test_days_sorted(self):
"""Проверка сортировки дней"""
days = get_days()
assert days == sorted(days)
def test_days_start(self):
"""Проверка первого дня"""
days = get_days()
assert days[0] == "2026-04-01"
def test_days_end(self):
"""Проверка последнего дня"""
days = get_days()
assert days[-1] == "2026-04-30"
class TestCreateModel:
"""Тесты для функции create_model"""
def test_model_creation(self):
"""Тест создания модели"""
model, variables, operators_set = create_model()
assert model is not None
assert variables is not None
assert operators_set is not None
assert len(operators_set) == len(OPERATORS)
def test_variables_count(self):
"""Тест количества переменных"""
model, variables, operators_set = create_model()
expected_count = len(get_days()) * len(SHIFTS) * len(OPERATORS)
assert len(variables) == expected_count
def test_operators_set(self):
"""Тест множества операторов"""
model, variables, operators_set = create_model()
assert operators_set == set(OPERATORS)
def test_model_has_constraints(self):
"""Тест наличия ограничений"""
model, variables, operators_set = create_model()
# Модель должна иметь ограничения
assert model.NumConstraints() > 0
def test_model_has_hints(self):
"""Тест наличия подсказок"""
model, variables, operators_set = create_model()
# Модель должна иметь подсказки
assert model.NumHints() > 0
class TestSolveModel:
"""Тесты для функции solve_model"""
def test_solve_returns_bool(self):
"""Тест возврата булевого значения"""
result = solve_model()
assert isinstance(result, bool)
def test_solve_with_valid_config(self):
"""Тест решения с валидной конфигурацией"""
# Это может занять время, поэтому тестуем только факт вызова
try:
result = solve_model()
# Результат может быть True или False в зависимости от конфигурации
assert isinstance(result, bool)
except Exception as e:
pytest.fail(f"Ошибка при решении модели: {e}")
class TestGetSolution:
"""Тесты для функции get_solution"""
def test_solution_structure(self):
"""Тест структуры решения"""
schedule = get_solution()
assert isinstance(schedule, dict)
assert len(schedule) > 0
def test_solution_days(self):
"""Тест дней в решении"""
schedule = get_solution()
days = get_days()
assert set(schedule.keys()) == set(days)
def test_solution_shifts(self):
"""Тест смен в решении"""
schedule = get_solution()
for day, day_shifts in schedule.items():
assert isinstance(day_shifts, dict)
assert len(day_shifts) == len(SHIFTS)
def test_solution_operators(self):
"""Тест операторов в решении"""
schedule = get_solution()
for day, day_shifts in schedule.items():
for shift_idx, shift_data in day_shifts.items():
assert isinstance(shift_data, dict)
assert len(shift_data) == len(OPERATORS)
def test_solution_values(self):
"""Тест значений в решении"""
schedule = get_solution()
for day, day_shifts in schedule.items():
for shift_idx, shift_data in day_shifts.items():
for op_name, value in shift_data.items():
assert isinstance(value, bool)
assert value in [True, False]
def test_solution_consistency(self):
"""Тест согласованности решения"""
schedule = get_solution()
# Каждый день и смена должны иметь ровно одного оператора
for day, day_shifts in schedule.items():
for shift_idx, shift_data in day_shifts.items():
active_operators = [op for op, value in shift_data.items() if value]
assert len(active_operators) == 1