Добавили тестов. но они пока нерабочие все
This commit is contained in:
1
tests/__init__.py
Normal file
1
tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Тесты для проекта модульности конфигурации
|
||||
140
tests/test_config.py
Normal file
140
tests/test_config.py
Normal file
@@ -0,0 +1,140 @@
|
||||
"""
|
||||
test_config.py - Тесты для конфигурации
|
||||
Проверяют корректность чтения и структуры config.py
|
||||
"""
|
||||
import pytest
|
||||
from config import YEAR, MONTH, SHIFTS, OPERATORS, OPERATOR_PREFERENCES
|
||||
|
||||
|
||||
class TestConfigConstants:
|
||||
"""Тесты для констант конфигурации"""
|
||||
|
||||
def test_year_is_int(self):
|
||||
"""Год должен быть целым числом"""
|
||||
assert isinstance(YEAR, int)
|
||||
assert YEAR == 2026
|
||||
|
||||
def test_month_is_int(self):
|
||||
"""Месяц должен быть целым числом"""
|
||||
assert isinstance(MONTH, int)
|
||||
assert MONTH == 4
|
||||
|
||||
def test_month_in_range(self):
|
||||
"""Месяц должен быть в диапазоне 1-12"""
|
||||
assert 1 <= MONTH <= 12
|
||||
|
||||
def test_shifts_is_list(self):
|
||||
"""Смены должны быть списком"""
|
||||
assert isinstance(SHIFTS, list)
|
||||
assert len(SHIFTS) == 4
|
||||
|
||||
def test_shifts_structure(self):
|
||||
"""Каждая смена должна быть кортежем из двух чисел"""
|
||||
for shift in SHIFTS:
|
||||
assert isinstance(shift, tuple)
|
||||
assert len(shift) == 2
|
||||
start, end = shift
|
||||
assert isinstance(start, (int, float))
|
||||
assert isinstance(end, (int, float))
|
||||
assert start < end
|
||||
|
||||
def test_operators_is_list(self):
|
||||
"""Операторы должны быть списком"""
|
||||
assert isinstance(OPERATORS, list)
|
||||
assert len(OPERATORS) > 0
|
||||
|
||||
def test_operators_not_empty(self):
|
||||
"""Список операторов не должен быть пустым"""
|
||||
assert len(OPERATORS) >= 1
|
||||
|
||||
def test_operators_strings(self):
|
||||
"""Все операторы должны быть строками"""
|
||||
for op in OPERATORS:
|
||||
assert isinstance(op, str)
|
||||
assert len(op) > 0
|
||||
|
||||
def test_operator_preferences_structure(self):
|
||||
"""Структура предпочтений должна быть корректной"""
|
||||
assert isinstance(OPERATOR_PREFERENCES, dict)
|
||||
assert len(OPERATOR_PREFERENCES) == len(OPERATORS)
|
||||
|
||||
def test_operator_preferences_values(self):
|
||||
"""Значения предпочтений должны быть словарями"""
|
||||
for op, prefs in OPERATOR_PREFERENCES.items():
|
||||
assert isinstance(prefs, dict)
|
||||
# Проверка, что ключи предпочтений корректны
|
||||
valid_keys = {'dates', 'day_of_week', 'shift', 'off_dates'}
|
||||
assert set(prefs.keys()).issubset(valid_keys)
|
||||
|
||||
|
||||
class TestConfigDates:
|
||||
"""Тесты для дат"""
|
||||
|
||||
def test_year_is_positive(self):
|
||||
"""Год должен быть положительным"""
|
||||
assert YEAR > 0
|
||||
|
||||
def test_month_is_valid(self):
|
||||
"""Месяц должен быть валидным (1-12)"""
|
||||
assert 1 <= MONTH <= 12
|
||||
|
||||
def test_shifts_time_valid(self):
|
||||
"""Время смены должно быть валидным (0-24)"""
|
||||
for start, end in SHIFTS:
|
||||
assert 0 <= start <= 24
|
||||
assert 0 <= end <= 24
|
||||
assert start < end
|
||||
|
||||
|
||||
class TestConfigOperators:
|
||||
"""Тесты для операторов"""
|
||||
|
||||
def test_operators_unique(self):
|
||||
"""Имена операторов должны быть уникальными"""
|
||||
assert len(OPERATORS) == len(set(OPERATORS))
|
||||
|
||||
def test_operators_no_empty_strings(self):
|
||||
"""Имена операторов не должны быть пустыми строками"""
|
||||
for op in OPERATORS:
|
||||
assert op.strip() != ""
|
||||
|
||||
def test_operators_no_special_chars(self):
|
||||
"""Имена операторов не должны содержать специальные символы"""
|
||||
for op in OPERATORS:
|
||||
assert not any(c in op for c in ['<', '>', '/', '\\', '|', ':', '*', '?', '"'])
|
||||
|
||||
|
||||
class TestConfigPreferences:
|
||||
"""Тесты для предпочтений операторов"""
|
||||
|
||||
def test_all_operators_have_preferences(self):
|
||||
"""Все операторы должны иметь предпочтения"""
|
||||
assert len(OPERATOR_PREFERENCES) == len(OPERATORS)
|
||||
|
||||
def test_dates_in_range(self):
|
||||
"""Дни в предпочтениях должны быть в диапазоне 1-31"""
|
||||
for prefs in OPERATOR_PREFERENCES.values():
|
||||
if 'dates' in prefs:
|
||||
for day in prefs['dates']:
|
||||
assert 1 <= day <= 31
|
||||
|
||||
def test_shift_in_range(self):
|
||||
"""Смена в предпочтениях должна быть в диапазоне 0-3"""
|
||||
for prefs in OPERATOR_PREFERENCES.values():
|
||||
if 'shift' in prefs:
|
||||
assert 0 <= prefs['shift'] <= 3
|
||||
|
||||
def test_day_of_week_valid(self):
|
||||
"""День недели в предпочтениях должен быть валидным"""
|
||||
for prefs in OPERATOR_PREFERENCES.values():
|
||||
if 'day_of_week' in prefs:
|
||||
day_str = prefs['day_of_week']
|
||||
# Проверяем, что это строка с валидным значением
|
||||
assert day_str.lower() in ['понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота', 'воскресенье']
|
||||
|
||||
def test_off_dates_in_range(self):
|
||||
"""Дни отдыха должны быть в диапазоне 1-31"""
|
||||
for prefs in OPERATOR_PREFERENCES.values():
|
||||
if 'off_dates' in prefs:
|
||||
for day in prefs['off_dates']:
|
||||
assert 1 <= day <= 31
|
||||
354
tests/test_models.py
Normal file
354
tests/test_models.py
Normal file
@@ -0,0 +1,354 @@
|
||||
"""
|
||||
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
|
||||
Reference in New Issue
Block a user