Добавьте файлы проекта.

This commit is contained in:
homyachelus 2026-10-29 11:08:09 +04:00
parent 7f0708321f
commit bcde8b809a
8 changed files with 221 additions and 0 deletions

44
README.md Normal file
View File

@ -0,0 +1,44 @@
\# Вариативная часть. Задание 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 | много | много | Пройден |

31
ShoeStore.Logic.sln Normal file
View File

@ -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", "{243ECAB7-9F51-4608-84B0-48DC7E3C5C3C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShoeStore.Tests", "ShoeStore.Tests\ShoeStore.Tests.csproj", "{FED8B0FF-E33E-493C-A134-43F3D05BD6CB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{243ECAB7-9F51-4608-84B0-48DC7E3C5C3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{243ECAB7-9F51-4608-84B0-48DC7E3C5C3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{243ECAB7-9F51-4608-84B0-48DC7E3C5C3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{243ECAB7-9F51-4608-84B0-48DC7E3C5C3C}.Release|Any CPU.Build.0 = Release|Any CPU
{FED8B0FF-E33E-493C-A134-43F3D05BD6CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FED8B0FF-E33E-493C-A134-43F3D05BD6CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FED8B0FF-E33E-493C-A134-43F3D05BD6CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FED8B0FF-E33E-493C-A134-43F3D05BD6CB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8E737E58-B5E1-47A9-8604-274B239853FC}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace ShoeStore.Logic
{
/// <summary>
/// Расчет показателей товара для каталога.
/// </summary>
public static class ProductCalculator
{
public const decimal DiscountPercent = 25m;
public const int ManyQuantityThreshold = 5;
/// <summary>
/// Возвращает цену товара с учетом скидки.
/// Скидка 25% предоставляется, если в предыдущем календарном месяце
/// (относительно даты расчета) по товару не было заказов.
/// </summary>
/// <param name="price">Цена товара в рублях.</param>
/// <param name="orderDates">Даты заказов товара (может быть пустым).</param>
/// <param name="calculationDate">Дата расчета.</param>
public static decimal CalculateDiscountedPrice(decimal price, IEnumerable<DateTime> 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);
}
/// <summary>
/// Возвращает признак количества: «много», если пар больше пяти, иначе «мало».
/// </summary>
/// <param name="totalQuantity">Количество пар суммарно по всем размерам.</param>
public static string GetQuantityLabel(int totalQuantity)
{
if (totalQuantity < 0)
{
throw new ArgumentOutOfRangeException(nameof(totalQuantity), "Количество не может быть отрицательным.");
}
return totalQuantity > ManyQuantityThreshold ? "много" : "мало";
}
}
}

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -0,0 +1 @@
[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)]

View File

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ShoeStore.Logic;
namespace ShoeStore.Tests
{
[TestClass]
public class ProductCalculatorTests
{
// Случай 1: заказов в предыдущем месяце нет - цена со скидкой
[TestMethod]
public void CalculateDiscountedPrice_NoOrdersInPreviousMonth_ReturnsPriceWithDiscount()
{
decimal price = 2000m;
List<DateTime> orderDates = new List<DateTime>();
DateTime calculationDate = new DateTime(2027, 6, 15);
decimal result = ProductCalculator.CalculateDiscountedPrice(price, orderDates, calculationDate);
Assert.AreEqual(1500m, result);
}
// Случай 2: есть заказ в предыдущем месяце - цена без скидки
[TestMethod]
public void CalculateDiscountedPrice_OrderInPreviousMonth_ReturnsPriceWithoutDiscount()
{
decimal price = 2000m;
List<DateTime> orderDates = new List<DateTime> { new DateTime(2027, 5, 10) };
DateTime calculationDate = new DateTime(2027, 6, 15);
decimal result = ProductCalculator.CalculateDiscountedPrice(price, orderDates, calculationDate);
Assert.AreEqual(2000m, result);
}
// Случай 3: граничное значение - «мало»
[TestMethod]
public void GetQuantityLabel_FivePairs_ReturnsFew()
{
string result = ProductCalculator.GetQuantityLabel(5);
Assert.AreEqual("мало", result);
}
// Случай 4: больше порогового - «много»
[TestMethod]
public void GetQuantityLabel_SixPairs_ReturnsMany()
{
string result = ProductCalculator.GetQuantityLabel(6);
Assert.AreEqual("много", result);
}
}
}

View File

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="MSTest" Version="3.6.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ShoeStore.Logic\ShoeStore.Logic.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
</Project>

BIN
result.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB