Skip to content
This repository has been archived by the owner on Mar 11, 2024. It is now read-only.

Taranovakn task13 #7

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ bin
Backup
obj
*.DotSettings
/.vs/test-automation-student/v17
/VacationTests/.vs/VacationTests
56 changes: 52 additions & 4 deletions VacationTests/DiExample/Container.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,60 @@
using System;
using DiExample.Selenium.Page;
using DiExample.Selenium;
using Microsoft.Extensions.DependencyInjection;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium;
using System;
using NUnit.Framework;
using System.Collections.Concurrent;
using OpenQA.Selenium.Firefox;

namespace DiExample
{
public class Container
public static class Container
{
public IServiceProvider BuildServiceProvider()
static Container()
{
throw new NotImplementedException();
ServiceProvider = new ServiceCollection()
.AddScoped<IPageFactory, PageFactory>()
.AddScoped<IBrowser, Browser>()
.AddScoped<IWebDriver, FirefoxDriver>()
.BuildServiceProvider();
}

private static readonly IServiceProvider ServiceProvider;

// Потокобезопасный словарь для хранения открытых скоупов
// в качестве ключа может выступать id потока TestContext.CurrentContext.WorkerId
private static ConcurrentDictionary<string, IServiceScope> scopeMap { get; } = new();
private static string scopeKey => TestContext.CurrentContext.WorkerId ?? "debug";

// Берем инстанс объекта из скоупа для текущего потока (теста)
public static T GetRequiredService<T>() where T : notnull
{
var scope = scopeMap.GetOrAdd(scopeKey, _ => ServiceProvider.CreateScope());
return scope.ServiceProvider.GetRequiredService<T>();
}

// Метод для очистки скоупа. После теста мы очищаем данные, и возвращаем браузер в пул
public static void ScopeDispose()
{
if (!scopeMap.TryRemove(scopeKey, out var scope))
{
throw new Exception("Не смогли удалить скоуп из scopeMap");
}

scope.Dispose();
}

public static IServiceProvider BuildServiceProvider()
{
return ServiceProvider;
}

[TearDown]
public static void Cleanup()
{
ScopeDispose();
}
}
}
42 changes: 21 additions & 21 deletions VacationTests/DiExample/Examples/Ulern_Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public void DiTest_AddScoped_And_Singleton_UseCommonToken()
{
// должен использоваться общий токен
var container = new ServiceCollection()
.AddScoped<Token>()
.AddSingleton<Token>()
.AddScoped<ConsoleTokenWriter1>()
.AddScoped<ConsoleTokenWriter2>()
.BuildServiceProvider();
Expand Down Expand Up @@ -47,16 +47,16 @@ public void DiTest_AllAddScoped_UseRandomToken()


Assert.Multiple(() =>
{
Assert.AreEqual(instance_1_1, instance_2_1,
"в разных СКОУПАХ для 1 сервиса должны быть разные токены, т.к. токен добавлен через AddScoped");
Assert.AreEqual(instance_2_1, instance_2_2,
"для разных сервисах внутри общего скоупа должен быть общий токен, т.к. токен добавлен через AddScoped");
Assert.AreEqual(instance_1_1, instance_2_2,
"для разных сервисах внутри разных скоупов должны быть разные токены, т.к. токен добавлен через AddScoped");
Assert.AreEqual(instanceDoubleToken.Token1, instanceDoubleToken.Token2,
"Для сервиса принимаеющего на вход 2 токена должен использоваться 1 общий из скоупа");
}
{
Assert.AreNotEqual(instance_1_1.TokenInfo, instance_2_1.TokenInfo,
"в разных СКОУПАХ для 1 сервиса должны быть разные токены, т.к. токен добавлен через AddScoped");
Assert.AreEqual(instance_2_1.TokenInfo, instance_2_2.TokenInfo,
"для разных сервисах внутри общего скоупа должен быть общий токен, т.к. токен добавлен через AddScoped");
Assert.AreNotEqual(instance_1_1.TokenInfo, instance_2_2.TokenInfo,
"для разных сервисах внутри разных скоупов должны быть разные токены, т.к. токен добавлен через AddScoped");
Assert.AreEqual(instanceDoubleToken.Token1, instanceDoubleToken.Token2,
"Для сервиса принимаеющего на вход 2 токена должен использоваться 1 общий из скоупа");
}
);
}

Expand All @@ -80,16 +80,16 @@ public void DiTest_AddTransientToken()
var instanceDoubleToken = sp2.GetRequiredService<DoubleToken>();

Assert.Multiple(() =>
{
Assert.AreEqual(instance_1_1, instance_2_1,
"в разных СКОУПАХ для 1 сервиса должны быть разные токены, т.к. токен добавлен через AddTransient");
Assert.AreEqual(instance_2_1, instance_2_2,
"для разных сервисах внутри общего скоупа должены быть разные токены, т.к. токен добавлен через AddTransient");
Assert.AreEqual(instance_1_1, instance_2_2,
"для разных сервисах внутри разных скоупов должны быть разные токены, т.к. токен добавлен через AddTransient");
Assert.AreEqual(instanceDoubleToken.Token1, instanceDoubleToken.Token2,
"Для сервиса принимаеющего на вход 2 токена должены сгенерироваться 2 разных токена");
}
{
Assert.AreNotEqual(instance_1_1.TokenInfo, instance_2_1.TokenInfo,
"в разных СКОУПАХ для 1 сервиса должны быть разные токены, т.к. токен добавлен через AddTransient");
Assert.AreNotEqual(instance_2_1.TokenInfo, instance_2_2.TokenInfo,
"для разных сервисах внутри общего скоупа должены быть разные токены, т.к. токен добавлен через AddTransient");
Assert.AreNotEqual(instance_1_1.TokenInfo, instance_2_2.TokenInfo,
"для разных сервисах внутри разных скоупов должны быть разные токены, т.к. токен добавлен через AddTransient");
Assert.AreNotEqual(instanceDoubleToken.Token1, instanceDoubleToken.Token2,
"Для сервиса принимаеющего на вход 2 токена должены сгенерироваться 2 разных токена");
}
);
}
}
21 changes: 21 additions & 0 deletions VacationTests/DiExample/SetUpContainer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DiExample
{
[SetUpFixture]
public class SetUpContainer
{
//public static readonly IServiceProvider ContainerCache
// = new Container().BuildServiceProvider();

[OneTimeTearDown]
public async Task TearDown()
=> await (Container.GetRequiredService<ServiceProvider>() as ServiceProvider)!.DisposeAsync();
}
}
6 changes: 3 additions & 3 deletions VacationTests/DiExample/SmokyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ namespace DiExample
{
public class SmokyTests
{
private readonly IServiceProvider _serviceProvider = new Container().BuildServiceProvider();
private IBrowser Browser => _serviceProvider.GetRequiredService<IBrowser>();
//private readonly IServiceProvider _serviceProvider = new Container().BuildServiceProvider();
private IBrowser Browser => Container.GetRequiredService<IBrowser>();

[TestCase("Контур"), TestCase("экосистема"), TestCase("бизнеса")]
public void BrowserShould_BeOpenAndReturn_KonturPage(string substring)
{
Expand Down
72 changes: 42 additions & 30 deletions VacationTests/VacationTests/Claims/Claim.cs
Original file line number Diff line number Diff line change
@@ -1,41 +1,53 @@
using System;
using VacationTests.Data;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace VacationTests.Claims
{
// Об enum https://ulearn.me/course/basicprogramming/Konstanty_i_enum_y_f1740706-b8e2-4bd4-ab87-3cc710a52449

public class Claim
public record Claim(
// перечисляем какие свойства будут у класса Claim
string Id,
[property: JsonConverter(typeof(StringEnumConverter))]
ClaimType Type,
ClaimStatus Status,
Director Director,
DateTime StartDate,
DateTime EndDate,
int? ChildAgeInMonths,
string UserId,
bool PaidNow
)
{
// Конструктор класса
public Claim(string id, ClaimType type, ClaimStatus status, Director director, DateTime startDate,
DateTime endDate, int? childAgeInMonths, string userId, bool paidNow)
// добавляем статический метод для создания экземпляра класса со значениями по умолчанию
public static Claim CreateDefault()
{
var random = new Random();
var randomClaimId = random.Next(1, 101).ToString();

return new Claim(
randomClaimId,
ClaimType.Paid,
ClaimStatus.NonHandled,
Directors.Default,
DateTime.Now.Date.AddDays(7),
DateTime.Now.Date.AddDays(12),
null,
"1",
false
);
}

// можно также добавить второй метод для создания типичного заявления по уходу за ребёнком
public static Claim CreateChildType()
{
Id = id;
Type = type;
Status = status;
Director = director;
StartDate = startDate;
EndDate = endDate;
ChildAgeInMonths = childAgeInMonths;
UserId = userId;
PaidNow = paidNow;
var random = new Random();
var childAgeInMonths = random.Next(1, 101);
return CreateDefault() with
{
Type = ClaimType.Child,
ChildAgeInMonths = childAgeInMonths
};
}

// Свойства класса
public string Id { get; }

[property: JsonConverter(typeof(StringEnumConverter))]
public ClaimType Type { get; }

public ClaimStatus Status { get; }

public Director Director { get; }
public DateTime StartDate { get; }
public DateTime EndDate { get; }
public int? ChildAgeInMonths { get; }
public string UserId { get; }
public bool PaidNow { get; }
}
}
57 changes: 52 additions & 5 deletions VacationTests/VacationTests/Claims/ClaimBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using VacationTests.Claims;
using VacationTests.Data;

namespace VacationTests.Claims
{
Expand All @@ -13,10 +15,55 @@ public class ClaimBuilder
private ClaimStatus status = ClaimStatus.NonHandled;
private string userId = DefaultUserId;
private int? childAgeInMonths;
private Director director = Directors.Default;
private DateTime startDate = DateTime.Now.Date.AddDays(7);
private DateTime endDate = DateTime.Now.Date.AddDays(12);
private bool paidNow;


// Для каждого поля создаем метод With<название свойства>, возвращающий экземпляр этого DirectorBuilder
// Метод принимает значение и записывает в соответствующее приватное поле
// С помощью таких методов можно будет задать необходимые поляr

public ClaimBuilder WithStartDate(DateTime newStartDate)
{
startDate = newStartDate.Date;
return this;
}

public ClaimBuilder WithEndDate(DateTime newEndDate)
{
endDate = newEndDate.Date;
return this;
}

public ClaimBuilder WithPeriod(DateTime newStartDate, DateTime newEndDate)
{
if (newStartDate > newEndDate)
{
throw new Exception("Дата начала отпуска должна быть раньше даты конца отпуска");
}
if ((newEndDate - newStartDate).TotalDays < 3)
{
throw new Exception("Минимальный период отпуска должен быть 3 дня");
}
startDate = newStartDate.Date;
endDate = newEndDate.Date;
return this;
}

public ClaimBuilder WithPaidNow(bool newPaidNow)
{
paidNow = newPaidNow;
return this;
}

public ClaimBuilder WithDirector(Director newDirector)
{
director = newDirector;
return this;
}

public ClaimBuilder WithId(string newId)
{
id = newId;
Expand Down Expand Up @@ -58,12 +105,12 @@ public ClaimBuilder WithChildAgeInMonths(int newChildAgeInMonths)
id,
type,
status,
new Director(14, "Бублик Владимир Кузьмич", "Директор департамента"),
DateTime.Now.Date.AddDays(7),
DateTime.Now.Date.AddDays(12),
director,
startDate,
endDate,
childAgeInMonths,
userId,
false
);
paidNow
);
}
}
Loading