diff --git a/README.md.txt b/README.md.txt new file mode 100644 index 0000000..10354d6 --- /dev/null +++ b/README.md.txt @@ -0,0 +1,21 @@ +# Вариативная часть. Задание 5: тестирование программных модулей + +Проект ShoeStore.Logic содержит класс ProductCalculator (Приложение 4), проект ShoeStore.Tests- модульные тесты MSTest. + +## Протокол тестирования + +Фреймворк модульного тестирования: MSTest(.NET 8). + +Порядок запуска тестов: +1. Открыть решение в Visual Studio 2022. +2. Меню «Тест»->«Обозреватель тестов». +3. Нажать «Запустить все тесты в представлении». + +Запуск из командной строки (в папке решения):dotnet test + +| № | Проверяемый случай | Входные данные | Ожидаемый результат | Фактический результат | Статус | +|---|---|---|---|---|---| +| 1 | Заказов в предыдущем месяце нет | Цена 2000; заказов нет; дата расчета 15.06.2027 | 1500 | 1500 | Пройден | +| 2 | Есть заказ в предыдущем месяце | Цена 2000; заказ 10.05.2027; дата расчета 15.06.2027 | 2000 | 2000 | Пройден | +| 3 | Граничное значение количества | Количество пар: 5 | мало | мало | Пройден | +| 4 | Количество больше порогового | Количество пар: 6 | много | много | Пройден | \ No newline at end of file diff --git a/ShoeStore.Logic.sln b/ShoeStore.Logic.sln new file mode 100644 index 0000000..770a1eb --- /dev/null +++ b/ShoeStore.Logic.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.37216.2 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShoeStore.Logic", "ShoeStore.Logic\ShoeStore.Logic.csproj", "{3F34B55B-B77D-4486-8DFF-8394D40D3586}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShoeStore.Test", "ShoeStore.Test\ShoeStore.Test.csproj", "{B283CB41-3F69-4930-B264-6DA46A78183A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3F34B55B-B77D-4486-8DFF-8394D40D3586}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F34B55B-B77D-4486-8DFF-8394D40D3586}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F34B55B-B77D-4486-8DFF-8394D40D3586}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F34B55B-B77D-4486-8DFF-8394D40D3586}.Release|Any CPU.Build.0 = Release|Any CPU + {B283CB41-3F69-4930-B264-6DA46A78183A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B283CB41-3F69-4930-B264-6DA46A78183A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B283CB41-3F69-4930-B264-6DA46A78183A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B283CB41-3F69-4930-B264-6DA46A78183A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A2A00E2D-1D52-47BC-97E0-BB2296C60A3B} + EndGlobalSection +EndGlobal diff --git a/ShoeStore.Logic/ProductCalculator.cs b/ShoeStore.Logic/ProductCalculator.cs new file mode 100644 index 0000000..795620d --- /dev/null +++ b/ShoeStore.Logic/ProductCalculator.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ShoeStore.Logic +{ + /// + /// Расчет показателей товара для каталога. + /// + public static class ProductCalculator + { + public const decimal DiscountPercent = 25m; + public const int ManyQuantityThreshold = 5; + + /// + /// Возвращает цену товара с учетом скидки. + /// Скидка 25% предоставляется, если в предыдущем календарном месяце + /// (относительно даты расчета) по товару не было заказов. + /// + /// Цена товара в рублях. + /// Даты заказов товара (может быть пустым). + /// Дата расчета. + public static decimal CalculateDiscountedPrice(decimal price, IEnumerable orderDates, DateTime calculationDate) + { + if (price < 0) + { + throw new ArgumentOutOfRangeException(nameof(price), "Цена не может быть отрицательной."); + } + if (orderDates == null) + { + throw new ArgumentNullException(nameof(orderDates)); + } + + DateTime currentMonthStart = new DateTime(calculationDate.Year, calculationDate.Month, 1); + DateTime previousMonthStart = currentMonthStart.AddMonths(-1); + bool hasOrdersInPreviousMonth = orderDates.Any(date => date >= previousMonthStart && date < currentMonthStart); + + if (hasOrdersInPreviousMonth) + { + return price; + } + return Math.Round(price * (100m - DiscountPercent) / 100m, 2); + } + + /// + /// Возвращает признак количества: «много», если пар больше пяти, иначе «мало». + /// + /// Количество пар суммарно по всем размерам. + public static string GetQuantityLabel(int totalQuantity) + { + if (totalQuantity < 0) + { + throw new ArgumentOutOfRangeException(nameof(totalQuantity), "Количество не может быть отрицательным."); + } + return totalQuantity > ManyQuantityThreshold ? "много" : "мало"; + } + } +} diff --git a/ShoeStore.Logic/ShoeStore.Logic.csproj b/ShoeStore.Logic/ShoeStore.Logic.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/ShoeStore.Logic/ShoeStore.Logic.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/ShoeStore.Test/MSTestSettings.cs b/ShoeStore.Test/MSTestSettings.cs new file mode 100644 index 0000000..aaf278c --- /dev/null +++ b/ShoeStore.Test/MSTestSettings.cs @@ -0,0 +1 @@ +[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)] diff --git a/ShoeStore.Test/ProductCalculatorTest.cs b/ShoeStore.Test/ProductCalculatorTest.cs new file mode 100644 index 0000000..8658a88 --- /dev/null +++ b/ShoeStore.Test/ProductCalculatorTest.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using ShoeStore.Logic; + +namespace ShoeStore.Test +{ + [TestClass] + public sealed class ProductCalculatorTest + { + [TestMethod] + public void CalculateDiscountPrice_NoOrderslnPreviousMonth_ReturnsPriceWithDiscount() + { + decimal price = 2000m; + List orderDates = new List(); + DateTime calculationDate = new DateTime(2027,6,15); + + decimal result = ProductCalculator.CalculateDiscountedPrice(price, orderDates, calculationDate); + + Assert.AreEqual(1500m, result); + } + [TestMethod] + public void CalculateDiscountPrice_OrederlnPreviousMonth_ReturnPriceWinthoutDiscount() + { + decimal price = 2000m; + List orderDates = new List {new DateTime(2027,5,10)}; + DateTime calculationDate = new DateTime(2027,5,15); + + decimal result = ProductCalculator.CalculateDiscountedPrice(price, orderDates, calculationDate); + + Assert.AreEqual(1500m,result); + } + [TestMethod] + public void GetQuantityLabel_FivePairs_ReturnsFew() + { + string result = ProductCalculator.GetQuantityLabel(5); + + Assert.AreEqual("мало", result); + } + [TestMethod] + public void GetQuantityLabel_SixPairs_ReturnsMany() + { + string result = ProductCalculator.GetQuantityLabel(6); + + Assert.AreEqual("много", result); + } + } +} diff --git a/ShoeStore.Test/ShoeStore.Test.csproj b/ShoeStore.Test/ShoeStore.Test.csproj new file mode 100644 index 0000000..9c96869 --- /dev/null +++ b/ShoeStore.Test/ShoeStore.Test.csproj @@ -0,0 +1,23 @@ + + + + net8.0 + latest + enable + enable + + + + + + + + + + + + + + + +