Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ТП_23_ИСТ_1_1_Какушкина_Ольга_Витальевна_ЛР_7

.docx
Скачиваний:
0
Добавлен:
23.06.2025
Размер:
215.07 Кб
Скачать

МИНОБРНАУКИ РОССИИ

Ф едеральное государственное бюджетное образовательное учреждение высшего образования

НИЖЕГОРОДСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ

УНИВЕРСИТЕТ им. Р.Е.АЛЕКСЕЕВА

Институт радиоэлектроники и информационных технологий

Кафедра информатики и систем управления

ОТЧЕТ по лабораторной работе №7

(наименование темы проекта или работы)

по дисциплине

Технологии программирования

ТЕСТИРОВАНИЕ ПО

РУКОВОДИТЕЛЬ:

________________ Капранов С. Н.

(подпись) (фамилия, и.,о.)

СТУДЕНТ:

________________ Какушкина О.В

(подпись) (фамилия, и.,о.)

23-ИСТ-1-1

(шифр группы)

Работа защищена «___» ____________

С оценкой ________________________

Нижний Новгород 2025

ЦЕЛЬ РАБОТЫ

Изучение методов тестирования программного обеспечения. Тестирование программного обеспечения с помощью сценариев использования.

Тема проекта: ПО «Распознавания аномалий на коже по фотографиям высокой четкости» 2-3 человека.

Задание: Используя материалы курсовой работы составить список из минимум 10 тестовых сценариев.

При тестировании применяем граничное тестирование, чтобы проверить пороговые значения модели и ее предсказаний, также присутствуют базовые проверки для методов таких, как обработка изображений, запись результатов в файл и т.д.

Рисунок 1 - Таблица с описанием тестовых сценариев.

Рисунок 2 - Результат прохождения тестов.

Программный код:

import unittest import os import numpy as np import json from datetime import datetime from PIL import Image import tensorflow as tf from keras._tf_keras.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array from load_img_model import load_and_preprocess_image, model, log_result # Пути для тестов TEST_IMAGE_ECZEMA = "test_set/Eczema/2.jpg" TEST_IMAGE_DERMATITIS = "test_set/Atopic Dermatilis/1.jpg" TEST_INVALID_FILE = "test_set/invalid.html" TEST_SMALL_IMAGE = "test_images/small_image.jpg" MODEL_PATH = 'my_model2.h5' LOG_FILE = "results_log.json" class TestDermatitisClassifier(unittest.TestCase): @classmethod def setUpClass(cls): """Загрузка модели перед всеми тестами""" cls.model = tf.keras.models.load_model(MODEL_PATH) # def setUp(self): # """Создание тестовых файлов перед каждым тестом""" # # Создаем тестовые изображения если их нет # if not os.path.exists("test_images"): # print("создал") # os.makedirs("test_images") # # # # Создаем тестовое изображение экземы (пустышка) # # if not os.path.exists(TEST_IMAGE_ECZEMA): # # Image.new('RGB', (224, 224), color='red').save(TEST_IMAGE_ECZEMA) # # # # # Создаем тестовое изображение дерматита (пустышка) # # if not os.path.exists(TEST_IMAGE_DERMATITIS): # # Image.new('RGB', (224, 224), color='blue').save(TEST_IMAGE_DERMATITIS) # # # Создаем маленькое изображение # if not os.path.exists(TEST_SMALL_IMAGE): # Image.new('RGB', (10, 10)).save(TEST_SMALL_IMAGE) # # # Создаем невалидный файл # if not os.path.exists(TEST_INVALID_FILE): # with open(TEST_INVALID_FILE, 'w') as f: # f.write("not an image") def test_1_model_loading(self): """Тест загрузки модели""" self.assertIsNotNone(self.model) self.assertEqual(len(self.model.layers) > 3, True) def test_2_image_preprocessing(self): """Тест предобработки изображений""" img = load_img(TEST_IMAGE_ECZEMA, target_size=(224, 224)) img_array = img_to_array(img) / 255.0 img_array = np.expand_dims(img_array, axis=0) self.assertEqual(img_array.shape, (1, 224, 224, 3)) self.assertTrue(np.all(img_array >= 0)) self.assertTrue(np.all(img_array <= 1)) def test_3_model_predicts_eczema(self): """Тест классификации экземы""" img = load_img("test_set/Eczema/2.jpg", target_size=(224, 224)) img_array = img_to_array(img) / 255.0 img_array = np.expand_dims(img_array, axis=0) prediction = self.model.predict(img_array) confidence = float(prediction[0][0]) # Проверяем, что модель уверенно определяет экзему self.assertGreater(confidence, 0.3, f"Модель недостаточно уверена в экземе (confidence={confidence:.2f})") def test_4_model_predicts_dermatitis(self): """Тест классификации атопического дерматита""" img = load_img("test_set/Atopic Dermatilis/2.jpg", target_size=(224, 224)) img_array = img_to_array(img) / 255.0 img_array = np.expand_dims(img_array, axis=0) prediction = self.model.predict(img_array) confidence = float(prediction[0][0]) # Проверяем, что модель уверенно определяет дерматит self.assertLess(confidence, 0.05, f"Модель недостаточно уверена в дерматите (confidence={confidence:.2f})") def test_5_invalid_input_handling(self): """Тест обработки некорректных данных""" # Неподдерживаемый формат файла with self.assertRaises(Exception): img = load_img(TEST_INVALID_FILE, target_size=(224, 224)) img_array = img_to_array(img) / 255.0 self.model.predict(np.expand_dims(img_array, axis=0)) def test_6_result_logging(self): """Тест логирования результатов""" # Очищаем лог перед тестом if os.path.exists(LOG_FILE): os.remove(LOG_FILE) # Имитируем вызов функции логирования test_entry = { "image_path": TEST_IMAGE_ECZEMA, "predicted_label": "Eczema", "confidence_score": "95.5%", "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } # Записываем тестовую запись data = [] if os.path.exists(LOG_FILE): with open(LOG_FILE, 'r') as f: try: data = json.load(f) except json.JSONDecodeError: data = [] data.append(test_entry) with open(LOG_FILE, 'w') as f: json.dump(data, f, indent=4) # Проверяем что файл создан и содержит наши данные self.assertTrue(os.path.exists(LOG_FILE)) with open(LOG_FILE, 'r') as f: log_data = json.load(f) self.assertEqual(log_data[-1]["image_path"], TEST_IMAGE_ECZEMA) def test_7_performance(self): """Тест производительности""" import time img = load_img(TEST_IMAGE_ECZEMA, target_size=(224, 224)) img_array = img_to_array(img) / 255.0 img_array = np.expand_dims(img_array, axis=0) start_time = time.time() self.model.predict(img_array) end_time = time.time() execution_time = end_time - start_time self.assertLess(execution_time, 0.5) # Должно занимать менее 0.5 секунды def test_8_json_log_format(self): """Тест формата записи в JSON-лог""" test_image_path = "test_set/Eczema/2.jpg" test_image = load_and_preprocess_image(test_image_path) y_pred = model.predict(test_image) # Вызываем функцию логирования log_result(test_image_path, "Eczema", float(y_pred[0][0])) # Проверяем структуру файла with open("results_log.json", "r") as f: log_data = json.load(f) last_entry = log_data[-1] self.assertIn("image_path", last_entry) self.assertIn("predicted_label", last_entry) self.assertIn("confidence_score", last_entry) self.assertIn("timestamp", last_entry) self.assertTrue(last_entry["confidence_score"].endswith("%")) self.assertEqual(last_entry["predicted_label"] in ["Eczema", "Atopic Dermatitis"], True) # def test_9_confidence_thresholds(self): # """Тест граничных значений уверенности""" # # Подготовка тестовых данных # test_cases = [ # (0.24, "Atopic Dermatitis"), # Ниже порога # (0.25, "Eczema"), # На пороге # (0.75, "Eczema"), # Выше порога # (0.00, "Atopic Dermatitis"), # Минимальная уверенность # (1.00, "Eczema") # Максимальная уверенность # ] # # for confidence, expected_label in test_cases: # # Создаем mock-предсказание # mock_pred = np.array([[confidence]], dtype=np.float32) # # # Определяем ожидаемый вывод # if confidence >= 0.25: # expected_output = f"Предсказанный класс: Eczema с уверенностью: {confidence * 100:.2f}%" # else: # expected_output = (f"Модель не уверена. Предсказание: Atopic Dermatitis " # f"с уверенностью: {confidence * 100:.2f}% (меньше порога 25%)") # # # Проверяем логику классификации без вывода # if confidence >= 0.25: # self.assertEqual("Eczema", expected_label) # else: # self.assertEqual("Atopic Dermatitis", expected_label) def test_confidence_below_threshold(self): """Граничный тест: уверенность чуть ниже порога (0.24)""" confidence = 0.24 mock_pred = np.array([[confidence]], dtype=np.float32) # Проверка классификации predicted_label = "Eczema" if confidence >= 0.25 else "Atopic Dermatitis" self.assertEqual(predicted_label, "Atopic Dermatitis") # Проверка формата сообщения output_message = (f"Модель не уверена. Предсказание: Atopic Dermatitis " f"с уверенностью: {confidence * 100:.2f}% (меньше порога 25%)") self.assertIn("не уверена", output_message) self.assertIn("24.00%", output_message) def test_confidence_at_threshold(self): """Граничный тест: уверенность на пороге (0.25)""" confidence = 0.25 mock_pred = np.array([[confidence]], dtype=np.float32) # Проверка переключения класса predicted_label = "Eczema" if confidence >= 0.25 else "Atopic Dermatitis" self.assertEqual(predicted_label, "Eczema") # Проверка формата вывода output_message = f"Предсказанный класс: Eczema с уверенностью: {confidence * 100:.2f}%" self.assertNotIn("не уверена", output_message) self.assertEqual(output_message, "Предсказанный класс: Eczema с уверенностью: 25.00%") def test_confidence_above_threshold(self): """Граничный тест: уверенность выше порога (0.26)""" confidence = 0.26 mock_pred = np.array([[confidence]], dtype=np.float32) # Проверка что модель не переключается обратно predicted_label = "Eczema" if confidence >= 0.25 else "Atopic Dermatitis" self.assertEqual(predicted_label, "Eczema") # Проверка формата вывода output_message = f"Предсказанный класс: Eczema с уверенностью: {confidence * 100:.2f}%" self.assertTrue(output_message.startswith("Предсказанный класс: Eczema")) def test_minimal_confidence(self): """Граничный тест: минимальная уверенность (0.00)""" confidence = 0.00 mock_pred = np.array([[confidence]], dtype=np.float32) # Проверка обработки нулевой уверенности predicted_label = "Eczema" if confidence >= 0.25 else "Atopic Dermatitis" self.assertEqual(predicted_label, "Atopic Dermatitis") # Проверка сообщения output_message = (f"Модель не уверена. Предсказание: Atopic Dermatitis " f"с уверенностью: {confidence * 100:.2f}% (меньше порога 25%)") self.assertIn("0.00%", output_message) def test_maximal_confidence(self): """Граничный тест: максимальная уверенность (1.00)""" confidence = 1.00 mock_pred = np.array([[confidence]], dtype=np.float32) # Проверка обработки полной уверенности predicted_label = "Eczema" if confidence >= 0.25 else "Atopic Dermatitis" self.assertEqual(predicted_label, "Eczema") # Проверка точного соответствия вывода output_message = f"Предсказанный класс: Eczema с уверенностью: {confidence * 100:.2f}%" self.assertEqual(output_message, "Предсказанный класс: Eczema с уверенностью: 100.00%") def test_precision_threshold(self): """Дополнительный тест: проверка точности порога (0.249 vs 0.250)""" # Проверка что 0.249 -> Atopic Dermatitis self.assertEqual("Eczema" if 0.249 >= 0.25 else "Atopic Dermatitis", "Atopic Dermatitis") # Проверка что 0.250 -> Eczema self.assertEqual("Eczema" if 0.250 >= 0.25 else "Atopic Dermatitis", "Eczema") # def test_10_grayscale_image_handling(self): # """Тест обработки изображений в градациях серого на основе реальных изображений""" # # Создаем временную директорию если ее нет # if not os.path.exists("test_images"): # os.makedirs("test_images") # # # Берем реальное тестовое изображение и создаем его grayscale версию # original_image_path = TEST_IMAGE_ECZEMA # Используем тестовое изображение экземы # gray_image_path = "test_images/gray_" + os.path.basename(original_image_path) # # try: # # Создаем grayscale версию изображения # with Image.open(original_image_path) as img: # gray_img = img.convert('L') # gray_img.save(gray_image_path) # # # Проверяем что grayscale изображение создано # self.assertTrue(os.path.exists(gray_image_path)) # # # Загружаем и обрабатываем grayscale изображение # img = load_img(gray_image_path, target_size=(224, 224)) # img_array = img_to_array(img) / 255.0 # # # Проверяем что изображение было конвертировано в RGB (3 канала) # self.assertEqual(img_array.shape, (224, 224, 3), # "Grayscale изображение не было конвертировано в RGB") # # # Проверяем предсказание на grayscale изображении # img_array = np.expand_dims(img_array, axis=0) # prediction = self.model.predict(img_array) # confidence = float(prediction[0][0]) # # # Проверяем что предсказание работает # self.assertTrue(0 <= confidence <= 1, # f"Уверенность {confidence} вне допустимого диапазона") # # # Дополнительная проверка: сравниваем предсказания оригинального и grayscale изображения # original_img = load_img(original_image_path, target_size=(224, 224)) # original_array = img_to_array(original_img) / 255.0 # original_array = np.expand_dims(original_array, axis=0) # original_prediction = float(self.model.predict(original_array)[0][0]) # # # Разница в предсказаниях не должна быть слишком большой # diff = abs(original_prediction - confidence) # print('разница = ', diff) # self.assertLess(diff, 0.3, # f"Слишком большая разница ({diff:.2f}) между предсказаниями оригинального и grayscale изображений") # # finally: # # Удаляем временное grayscale изображение # if os.path.exists(gray_image_path): # os.remove(gray_image_path) # @classmethod # def tearDownClass(cls): # """Очистка после всех тестов""" # # Удаляем тестовые файлы # if os.path.exists(TEST_IMAGE_ECZEMA): # os.remove(TEST_IMAGE_ECZEMA) # if os.path.exists(TEST_IMAGE_DERMATITIS): # os.remove(TEST_IMAGE_DERMATITIS) # if os.path.exists(TEST_INVALID_FILE): # os.remove(TEST_INVALID_FILE) # if os.path.exists(TEST_SMALL_IMAGE): # os.remove(TEST_SMALL_IMAGE) # if os.path.exists("test_images/gray.jpg"): # os.remove("test_images/gray.jpg") # if os.path.exists("test_images"): # os.rmdir("test_images") if __name__ == '__main__': unittest.main()

Вывод: в ходе выполнения лабораторной работы были изучены основы тестирования ПО, полученные навыки применены на практике для написания тестовых сценарий.

9