From 0238d674172e74165a78571819914b57fa42f968 Mon Sep 17 00:00:00 2001 From: Gennady Verdel Date: Tue, 6 Jul 2021 21:03:22 +0300 Subject: [PATCH] feat(configuration): added configuration section-related functionality #84 --- .../Attest.Testing.Contracts.csproj | 3 +- .../IConfigurationSectionKeySplitter.cs | 10 +++ .../IConfigurationSectionValueProvider.cs | 19 +++++ .../Attest.Testing.Core.Specs.csproj | 13 ++- .../Configuration/Configuration.feature | 16 ++++ .../ConfigurationScenarioDataStore.cs | 50 +++++++++++ .../Configuration/ConfigurationSteps.cs | 83 +++++++++++++++++++ .../AnotherProviderBuilder.cs | 0 .../InheritanceProviderBuilder.cs | 0 .../{ => Serialization}/Serialization.feature | 0 .../SerializationScenarioDataStore.cs | 0 .../{ => Serialization}/SerializationSteps.cs | 0 .../SimpleProviderBuilder.cs | 0 .../Attest.Testing.Core.csproj | 3 +- .../ConfigurationSectionValueProvider.cs | 34 ++++++++ .../EnvironmentVariableKeySplitter.cs | 15 ++++ .../contents/Attest.Testing.Contracts.nuspec | 1 + .../contents/Attest.Tests.Core.nuspec | 1 + 18 files changed, 245 insertions(+), 3 deletions(-) create mode 100644 Attest.Testing.Contracts/Configuration/IConfigurationSectionKeySplitter.cs create mode 100644 Attest.Testing.Contracts/Configuration/IConfigurationSectionValueProvider.cs create mode 100644 Attest.Testing.Core.Specs/Configuration/Configuration.feature create mode 100644 Attest.Testing.Core.Specs/Configuration/ConfigurationScenarioDataStore.cs create mode 100644 Attest.Testing.Core.Specs/Configuration/ConfigurationSteps.cs rename Attest.Testing.Core.Specs/{ => Serialization}/AnotherProviderBuilder.cs (100%) rename Attest.Testing.Core.Specs/{ => Serialization}/InheritanceProviderBuilder.cs (100%) rename Attest.Testing.Core.Specs/{ => Serialization}/Serialization.feature (100%) rename Attest.Testing.Core.Specs/{ => Serialization}/SerializationScenarioDataStore.cs (100%) rename Attest.Testing.Core.Specs/{ => Serialization}/SerializationSteps.cs (100%) rename Attest.Testing.Core.Specs/{ => Serialization}/SimpleProviderBuilder.cs (100%) create mode 100644 Attest.Testing.Core/Configuration/ConfigurationSectionValueProvider.cs create mode 100644 Attest.Testing.Core/Configuration/EnvironmentVariableKeySplitter.cs diff --git a/Attest.Testing.Contracts/Attest.Testing.Contracts.csproj b/Attest.Testing.Contracts/Attest.Testing.Contracts.csproj index e71eeaf2..7528dffb 100644 --- a/Attest.Testing.Contracts/Attest.Testing.Contracts.csproj +++ b/Attest.Testing.Contracts/Attest.Testing.Contracts.csproj @@ -1,4 +1,4 @@ - + false netstandard2.0 @@ -12,6 +12,7 @@ true + diff --git a/Attest.Testing.Contracts/Configuration/IConfigurationSectionKeySplitter.cs b/Attest.Testing.Contracts/Configuration/IConfigurationSectionKeySplitter.cs new file mode 100644 index 00000000..a6e684be --- /dev/null +++ b/Attest.Testing.Contracts/Configuration/IConfigurationSectionKeySplitter.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +// ReSharper disable once CheckNamespace +namespace Attest.Testing.Configuration +{ + public interface IConfigurationSectionKeySplitter + { + IEnumerable Split(string key); + } +} diff --git a/Attest.Testing.Contracts/Configuration/IConfigurationSectionValueProvider.cs b/Attest.Testing.Contracts/Configuration/IConfigurationSectionValueProvider.cs new file mode 100644 index 00000000..cc424dbd --- /dev/null +++ b/Attest.Testing.Contracts/Configuration/IConfigurationSectionValueProvider.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Configuration; + +// ReSharper disable once CheckNamespace +namespace Attest.Testing.Configuration +{ + /// + /// Provides facilities for interacting with configuration sections. + /// + public interface IConfigurationSectionValueProvider + { + /// + /// Gets the value for the configuration section by its key. + /// + /// The configuration. + /// The section key. + /// + string GetValue(IConfiguration configuration, string key); + } +} diff --git a/Attest.Testing.Core.Specs/Attest.Testing.Core.Specs.csproj b/Attest.Testing.Core.Specs/Attest.Testing.Core.Specs.csproj index e6db4603..03d67b15 100644 --- a/Attest.Testing.Core.Specs/Attest.Testing.Core.Specs.csproj +++ b/Attest.Testing.Core.Specs/Attest.Testing.Core.Specs.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 false @@ -29,9 +29,20 @@ + + + True + + Always + + + SpecFlowSingleFileGenerator + Configuration.feature.cs + + \ No newline at end of file diff --git a/Attest.Testing.Core.Specs/Configuration/Configuration.feature b/Attest.Testing.Core.Specs/Configuration/Configuration.feature new file mode 100644 index 00000000..54f5a3a2 --- /dev/null +++ b/Attest.Testing.Core.Specs/Configuration/Configuration.feature @@ -0,0 +1,16 @@ +Feature: Configuration + In order to support development with configuration + As an app developer + I want the framework to be able to resolve value by key + +Scenario: Resolving simple value by an existing key should return value + Given The configuration uses environment variable compatible key splitter + And The configuration contains the key "key" mapped to value "value" + When I get the value by this key + Then The value is resolved successfully + +Scenario: Resolving simple value by a non-existing key should return null + Given The configuration uses environment variable compatible key splitter + And The configuration does not contain the key "key" + When I get the value by this key + Then The value is returned as null \ No newline at end of file diff --git a/Attest.Testing.Core.Specs/Configuration/ConfigurationScenarioDataStore.cs b/Attest.Testing.Core.Specs/Configuration/ConfigurationScenarioDataStore.cs new file mode 100644 index 00000000..94de7ec9 --- /dev/null +++ b/Attest.Testing.Core.Specs/Configuration/ConfigurationScenarioDataStore.cs @@ -0,0 +1,50 @@ +using Attest.Fake.Core; +using Attest.Testing.Configuration; +using Attest.Testing.Context.SpecFlow; +using Microsoft.Extensions.Configuration; +using TechTalk.SpecFlow; + +namespace Attest.Testing.Core.Specs +{ + internal sealed class ConfigurationScenarioDataStore : ScenarioDataStoreBase + { + public ConfigurationScenarioDataStore(ScenarioContext scenarioContext) : base(scenarioContext) + {} + + public string Key + { + get => GetValue(); + set => SetValue(value); + } + + public string ExpectedValue + { + get => GetValue(); + set => SetValue(value); + } + + public string ActualValue + { + get => GetValue(); + set => SetValue(value); + } + + public IConfigurationSectionKeySplitter KeySplitter + { + get => GetValue(); + set => SetValue(value); + } + + public IFake Configuration + { + get => GetValue>(); + set => SetValue(value); + } + + public IFake ConfigurationSection + { + get => GetValue>(); + set => SetValue(value); + } + } +} diff --git a/Attest.Testing.Core.Specs/Configuration/ConfigurationSteps.cs b/Attest.Testing.Core.Specs/Configuration/ConfigurationSteps.cs new file mode 100644 index 00000000..a4bca623 --- /dev/null +++ b/Attest.Testing.Core.Specs/Configuration/ConfigurationSteps.cs @@ -0,0 +1,83 @@ +using Attest.Fake.Core; +using Attest.Fake.Moq; +using Attest.Testing.Configuration; +using FluentAssertions; +using Microsoft.Extensions.Configuration; +using TechTalk.SpecFlow; + +namespace Attest.Testing.Core.Specs +{ + [Binding] + internal sealed class ConfigurationSteps + { + private readonly ConfigurationScenarioDataStore _configurationScenarioDataStore; + private readonly IFakeFactory _fakeFactory; + + public ConfigurationSteps(ScenarioContext scenarioContext) + { + _configurationScenarioDataStore = new ConfigurationScenarioDataStore(scenarioContext); + _fakeFactory = new FakeFactory(); + } + + [Given(@"The configuration uses environment variable compatible key splitter")] + public void GivenTheConfigurationUsesEnvironmentVariableCompatibleKeySplitter() + { + _configurationScenarioDataStore.KeySplitter = new EnvironmentVariableKeySplitter(); + } + + [Given(@"The configuration contains the key ""(.*)"" mapped to value ""(.*)""")] + public void GivenTheConfigurationContainsTheKeyMappedToValue(string key, string value) + { + _configurationScenarioDataStore.Key = key; + _configurationScenarioDataStore.ExpectedValue = value; + _configurationScenarioDataStore.Configuration = _fakeFactory.CreateFake(); + _configurationScenarioDataStore.ConfigurationSection = _fakeFactory.CreateFake(); + _configurationScenarioDataStore.ConfigurationSection + .Setup(t => t.Value) + .Callback(() => _configurationScenarioDataStore.ExpectedValue); + _configurationScenarioDataStore.Configuration + .Setup(t => t.GetSection(key)) + .Callback(() => _configurationScenarioDataStore.ConfigurationSection.Object); + } + + [Given(@"The configuration does not contain the key ""(.*)""")] + public void GivenTheConfigurationDoesNotContainTheKeyMappedToValue(string key) + { + _configurationScenarioDataStore.Key = key; + _configurationScenarioDataStore.Configuration = _fakeFactory.CreateFake(); + _configurationScenarioDataStore.Configuration + .Setup(t => t.GetSection(key)) + .Callback(() => null); + } + + [When(@"I get the value by this key")] + public void WhenIGetTheValueByThisKey() + { + //TODO: Inject/Resolve + var configurationSectionValueProvider = + new ConfigurationSectionValueProvider(_configurationScenarioDataStore.KeySplitter); + var value = configurationSectionValueProvider.GetValue( + _configurationScenarioDataStore.Configuration.Object, + _configurationScenarioDataStore.Key); + _configurationScenarioDataStore.ActualValue = value; + } + + [Then(@"The value is resolved successfully")] + public void ThenTheValueIsResolvedSuccessfully() + { + _configurationScenarioDataStore + .ActualValue + .Should() + .Be(_configurationScenarioDataStore.ExpectedValue); + } + + [Then(@"The value is returned as null")] + public void ThenTheValueIsReturnedAsNull() + { + _configurationScenarioDataStore + .ActualValue + .Should() + .BeNull(); + } + } +} \ No newline at end of file diff --git a/Attest.Testing.Core.Specs/AnotherProviderBuilder.cs b/Attest.Testing.Core.Specs/Serialization/AnotherProviderBuilder.cs similarity index 100% rename from Attest.Testing.Core.Specs/AnotherProviderBuilder.cs rename to Attest.Testing.Core.Specs/Serialization/AnotherProviderBuilder.cs diff --git a/Attest.Testing.Core.Specs/InheritanceProviderBuilder.cs b/Attest.Testing.Core.Specs/Serialization/InheritanceProviderBuilder.cs similarity index 100% rename from Attest.Testing.Core.Specs/InheritanceProviderBuilder.cs rename to Attest.Testing.Core.Specs/Serialization/InheritanceProviderBuilder.cs diff --git a/Attest.Testing.Core.Specs/Serialization.feature b/Attest.Testing.Core.Specs/Serialization/Serialization.feature similarity index 100% rename from Attest.Testing.Core.Specs/Serialization.feature rename to Attest.Testing.Core.Specs/Serialization/Serialization.feature diff --git a/Attest.Testing.Core.Specs/SerializationScenarioDataStore.cs b/Attest.Testing.Core.Specs/Serialization/SerializationScenarioDataStore.cs similarity index 100% rename from Attest.Testing.Core.Specs/SerializationScenarioDataStore.cs rename to Attest.Testing.Core.Specs/Serialization/SerializationScenarioDataStore.cs diff --git a/Attest.Testing.Core.Specs/SerializationSteps.cs b/Attest.Testing.Core.Specs/Serialization/SerializationSteps.cs similarity index 100% rename from Attest.Testing.Core.Specs/SerializationSteps.cs rename to Attest.Testing.Core.Specs/Serialization/SerializationSteps.cs diff --git a/Attest.Testing.Core.Specs/SimpleProviderBuilder.cs b/Attest.Testing.Core.Specs/Serialization/SimpleProviderBuilder.cs similarity index 100% rename from Attest.Testing.Core.Specs/SimpleProviderBuilder.cs rename to Attest.Testing.Core.Specs/Serialization/SimpleProviderBuilder.cs diff --git a/Attest.Testing.Core/Attest.Testing.Core.csproj b/Attest.Testing.Core/Attest.Testing.Core.csproj index ba386a3e..1e9a670f 100644 --- a/Attest.Testing.Core/Attest.Testing.Core.csproj +++ b/Attest.Testing.Core/Attest.Testing.Core.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 false @@ -12,6 +12,7 @@ true + diff --git a/Attest.Testing.Core/Configuration/ConfigurationSectionValueProvider.cs b/Attest.Testing.Core/Configuration/ConfigurationSectionValueProvider.cs new file mode 100644 index 00000000..68c69627 --- /dev/null +++ b/Attest.Testing.Core/Configuration/ConfigurationSectionValueProvider.cs @@ -0,0 +1,34 @@ +using System.Linq; +using Microsoft.Extensions.Configuration; + +// ReSharper disable once CheckNamespace +namespace Attest.Testing.Configuration +{ + /// + public class ConfigurationSectionValueProvider : IConfigurationSectionValueProvider + { + private readonly IConfigurationSectionKeySplitter _configurationSectionKeySplitter; + + public ConfigurationSectionValueProvider(IConfigurationSectionKeySplitter configurationSectionKeySplitter) + { + _configurationSectionKeySplitter = configurationSectionKeySplitter; + } + + /// + public string GetValue(IConfiguration configuration, string key) + { + var sections = //key.Split(new[] {"__"}, StringSplitOptions.None) + _configurationSectionKeySplitter.Split(key) + .Where(x => !string.IsNullOrEmpty(x)) + .ToArray(); + IConfigurationSection section = null; + foreach (var sectionName in sections) + { + section = section == null ? configuration.GetSection(sectionName) : section.GetSection(sectionName); + } + + var value = section?.Value; + return value; + } + } +} diff --git a/Attest.Testing.Core/Configuration/EnvironmentVariableKeySplitter.cs b/Attest.Testing.Core/Configuration/EnvironmentVariableKeySplitter.cs new file mode 100644 index 00000000..5774e0a5 --- /dev/null +++ b/Attest.Testing.Core/Configuration/EnvironmentVariableKeySplitter.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +// ReSharper disable once CheckNamespace +namespace Attest.Testing.Configuration +{ + public sealed class EnvironmentVariableKeySplitter : IConfigurationSectionKeySplitter + { + /// + public IEnumerable Split(string key) + { + return key.Split(new[] {"__"}, StringSplitOptions.None); + } + } +} diff --git a/devops/pack/Attest.Testing.Contracts/contents/Attest.Testing.Contracts.nuspec b/devops/pack/Attest.Testing.Contracts/contents/Attest.Testing.Contracts.nuspec index 38d8db2c..54a34eaf 100644 --- a/devops/pack/Attest.Testing.Contracts/contents/Attest.Testing.Contracts.nuspec +++ b/devops/pack/Attest.Testing.Contracts/contents/Attest.Testing.Contracts.nuspec @@ -15,6 +15,7 @@ + diff --git a/devops/pack/Attest.Tests.Core/contents/Attest.Tests.Core.nuspec b/devops/pack/Attest.Tests.Core/contents/Attest.Tests.Core.nuspec index 204f4d97..74bf978c 100644 --- a/devops/pack/Attest.Tests.Core/contents/Attest.Tests.Core.nuspec +++ b/devops/pack/Attest.Tests.Core/contents/Attest.Tests.Core.nuspec @@ -27,6 +27,7 @@ +