Skip to content

Commit 9030f8d

Browse files
test(e2e): Refactor E2E tests to use appsettings or environment variables (#456)
Signed-off-by: Kyle Julian <[email protected]>
1 parent 5920937 commit 9030f8d

File tree

13 files changed

+183
-65
lines changed

13 files changed

+183
-65
lines changed

CONTRIBUTING.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,32 @@ The instructions above will generate a test project for you.
4646

4747
Use `dotnet test` to test the entire project.
4848

49+
### Running End-to-End (E2E) Integration Tests
50+
51+
To run the E2E integration tests for this repository, you need to set up your development environment as follows:
52+
53+
#### Prerequisites
54+
55+
- **Docker**: You must have Docker installed and running on your machine. You can use [Docker Desktop for Windows](https://www.docker.com/products/docker-desktop/) or install Docker on Linux/Mac OS. The E2E tests require Docker to spin up test containers.
56+
57+
#### Configuration
58+
59+
Each E2E test project contains an `appsettings.json` file. To enable E2E tests, ensure the following setting is present and set to `true`:
60+
61+
```json
62+
{
63+
"E2E": "true"
64+
}
65+
```
66+
67+
You can also set the `E2E` environment variable to `true` if you prefer not to modify the `appsettings.json` file.
68+
69+
An example E2E project are the Flagd Provider E2E tests, found [here](/test/OpenFeature.Contrib.Providers.Flagd.E2e.ProcessTest/appsettings.json).
70+
71+
If you want to disable E2E tests, set `"E2E": "false"` or remove the setting.
72+
73+
> **Note:** The E2E tests will be skipped if Docker is not running or if the `E2E` setting is not enabled in `appsettings.json`.
74+
4975
## Automated Changelog
5076

5177
Each time a release is published the changelogs will be generated automatically using [googleapis/release-please-action](https://github.com/googleapis/release-please-action). The tool will organise the changes based on the PR labels.

test/OpenFeature.Contrib.Providers.Flagd.E2e.Common/Steps/EvaluationStepDefinitionBase.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ namespace OpenFeature.Contrib.Providers.Flagd.E2e.Common;
1313
public abstract class EvaluationStepDefinitionsBase
1414
{
1515
private readonly ScenarioContext _scenarioContext;
16-
protected FeatureClient client;
17-
protected FeatureClient name;
16+
private FeatureClient client;
1817
private bool booleanFlagValue;
1918
private string stringFlagValue;
2019
private int intFlagValue;
@@ -38,14 +37,20 @@ public abstract class EvaluationStepDefinitionsBase
3837

3938
public EvaluationStepDefinitionsBase(ScenarioContext scenarioContext)
4039
{
41-
Skip.If(Environment.GetEnvironmentVariable("E2E") != "true");
4240
_scenarioContext = scenarioContext;
4341
}
4442

4543
[Given(@"a stable provider")]
4644
public void Givenastableprovider()
4745
{
48-
// done in sub-classes
46+
if (this._scenarioContext.TryGetValue<FeatureClient>("Client", out var client))
47+
{
48+
this.client = client;
49+
}
50+
else
51+
{
52+
throw new InvalidOperationException("Client not found in scenario context. Ensure the BeforeTestRun hook initializes the client.");
53+
}
4954
}
5055

5156
[When(@"a boolean flag with key ""(.*)"" is evaluated with default value ""(.*)""")]

test/OpenFeature.Contrib.Providers.Flagd.E2e.Common/Steps/FlagdStepDefinitionBase.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ namespace OpenFeature.Contrib.Providers.Flagd.E2e.Common;
1010
public abstract class FlagdStepDefinitionsBase
1111
{
1212
private readonly ScenarioContext _scenarioContext;
13-
protected FeatureClient client;
14-
protected FeatureClient name;
13+
private FeatureClient client;
1514
private bool booleanZeroValue;
1615
private string stringZeroValue;
1716
private int intZeroFlagValue;
@@ -26,14 +25,20 @@ public abstract class FlagdStepDefinitionsBase
2625

2726
public FlagdStepDefinitionsBase(ScenarioContext scenarioContext)
2827
{
29-
Skip.If(Environment.GetEnvironmentVariable("E2E") != "true");
3028
_scenarioContext = scenarioContext;
3129
}
3230

3331
[Given(@"a flagd provider is set")]
3432
public void GivenAFlagdProviderIsSet()
3533
{
36-
// done in subclasses
34+
if (this._scenarioContext.TryGetValue<FeatureClient>("Client", out var client))
35+
{
36+
this.client = client;
37+
}
38+
else
39+
{
40+
throw new InvalidOperationException("Client not found in scenario context. Ensure the BeforeTestRun hook initializes the client.");
41+
}
3742
}
3843

3944
[When(@"a PROVIDER_READY handler is added")]
Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,31 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<ItemGroup>
4-
<None
5-
Include="../../spec/specification/assets/gherkin/evaluation.feature"
6-
Link="../../../Features/%(Filename)%(Extension)"
7-
DestinationFolder="../../../Features/"
8-
CopyToOutputDirectory="PreserveNewest" />
4+
<None Include="../../spec/specification/assets/gherkin/evaluation.feature" Link="../../../Features/%(Filename)%(Extension)" DestinationFolder="../../../Features/" CopyToOutputDirectory="PreserveNewest" />
95
</ItemGroup>
106

117
<!-- TODO: add reconnect tests (remove exclusion) -->
128
<ItemGroup>
13-
<None
14-
Include="../../src/OpenFeature.Contrib.Providers.Flagd/flagd-testbed/gherkin/*.feature"
15-
Exclude="../../src/OpenFeature.Contrib.Providers.Flagd/flagd-testbed/gherkin/flagd-reconnect.feature"
16-
Link="../../../Features/%(Filename)%(Extension)"
17-
DestinationFolder="../../../Features/"
18-
CopyToOutputDirectory="PreserveNewest" />
9+
<None Include="../../src/OpenFeature.Contrib.Providers.Flagd/flagd-testbed/gherkin/*.feature" Exclude="../../src/OpenFeature.Contrib.Providers.Flagd/flagd-testbed/gherkin/flagd-reconnect.feature" Link="../../../Features/%(Filename)%(Extension)" DestinationFolder="../../../Features/" CopyToOutputDirectory="PreserveNewest" />
1910
</ItemGroup>
2011

2112
<ItemGroup>
22-
<ProjectReference
23-
Include="..\..\src\OpenFeature.Contrib.Providers.Flagd\OpenFeature.Contrib.Providers.Flagd.csproj" />
24-
<ProjectReference
25-
Include="..\OpenFeature.Contrib.Providers.Flagd.E2e.Common\OpenFeature.Contrib.Providers.Flagd.E2e.Common.csproj" />
13+
<ProjectReference Include="..\..\src\OpenFeature.Contrib.Providers.Flagd\OpenFeature.Contrib.Providers.Flagd.csproj" />
14+
<ProjectReference Include="..\OpenFeature.Contrib.Providers.Flagd.E2e.Common\OpenFeature.Contrib.Providers.Flagd.E2e.Common.csproj" />
2615
</ItemGroup>
2716

2817
<ItemGroup>
18+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
19+
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
20+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
2921
<PackageReference Include="Reqnroll.xUnit" Version="2.4.1" />
3022
<PackageReference Include="Testcontainers" Version="4.4.0" />
3123
</ItemGroup>
3224

25+
<ItemGroup>
26+
<None Update="appsettings.json">
27+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
28+
</None>
29+
</ItemGroup>
30+
3331
</Project>
Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
1+
using System.Threading.Tasks;
2+
using Microsoft.Extensions.Configuration;
13
using OpenFeature.Contrib.Providers.Flagd.E2e.Common;
24
using Reqnroll;
5+
using Xunit;
36

47
namespace OpenFeature.Contrib.Providers.Flagd.E2e.ProcessTest.Steps;
58

69
[Binding, Scope(Feature = "Flag evaluation")]
710
public class EvaluationStepDefinitionsProcess : EvaluationStepDefinitionsBase
811
{
9-
static EvaluationStepDefinitionsProcess()
12+
public EvaluationStepDefinitionsProcess(ScenarioContext scenarioContext) : base(scenarioContext)
1013
{
14+
}
15+
16+
[BeforeScenario]
17+
public static async Task BeforeScenarioAsync(ScenarioContext scenarioContext, FeatureContext featureContext)
18+
{
19+
var configuration = new ConfigurationBuilder()
20+
.AddJsonFile("appsettings.json", optional: true)
21+
.AddEnvironmentVariables()
22+
.Build();
23+
24+
Skip.If(configuration["E2E"] != "true", "Skipping test as E2E tests are disabled, enable them by updating the appsettings.json.");
25+
1126
var host = TestHooks.FlagdSyncTestBed.Container.Hostname;
1227
var port = TestHooks.FlagdSyncTestBed.Container.GetMappedPublicPort(8015);
1328

@@ -19,11 +34,11 @@ static EvaluationStepDefinitionsProcess()
1934
.Build()
2035
);
2136

22-
Api.Instance.SetProviderAsync("process-test-evaluation", flagdProvider).Wait(5000);
23-
}
37+
await Api.Instance.SetProviderAsync("process-test-evaluation", flagdProvider).ConfigureAwait(false);
2438

25-
public EvaluationStepDefinitionsProcess(ScenarioContext scenarioContext) : base(scenarioContext)
26-
{
27-
client = Api.Instance.GetClient("process-test-evaluation");
39+
var client = Api.Instance.GetClient("process-test-evaluation");
40+
41+
scenarioContext.Set(client, "Client");
42+
scenarioContext.Set(configuration, "Configuration");
2843
}
2944
}
Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
using System.Threading.Tasks;
2+
using Microsoft.Extensions.Configuration;
13
using OpenFeature.Contrib.Providers.Flagd.E2e.Common;
24
using Reqnroll;
5+
using Xunit;
36

47
namespace OpenFeature.Contrib.Providers.Flagd.E2e.ProcessTest.Steps;
58

@@ -8,8 +11,20 @@ namespace OpenFeature.Contrib.Providers.Flagd.E2e.ProcessTest.Steps;
811
[Scope(Feature = "flagd json evaluation")]
912
public class FlagdStepDefinitionsProcess : FlagdStepDefinitionsBase
1013
{
11-
static FlagdStepDefinitionsProcess()
14+
public FlagdStepDefinitionsProcess(ScenarioContext scenarioContext) : base(scenarioContext)
1215
{
16+
}
17+
18+
[BeforeScenario]
19+
public static async Task BeforeScenarioAsync(ScenarioContext scenarioContext)
20+
{
21+
var configuration = new ConfigurationBuilder()
22+
.AddJsonFile("appsettings.json", optional: true)
23+
.AddEnvironmentVariables()
24+
.Build();
25+
26+
Skip.If(configuration["E2E"] != "true", "Skipping test as E2E tests are disabled, enable them by updating the appsettings.json.");
27+
1328
var host = TestHooks.FlagdSyncTestBed.Container.Hostname;
1429
var port = TestHooks.FlagdSyncTestBed.Container.GetMappedPublicPort(8015);
1530

@@ -21,11 +36,11 @@ static FlagdStepDefinitionsProcess()
2136
.Build()
2237
);
2338

24-
Api.Instance.SetProviderAsync("process-test-flagd", flagdProvider).Wait(5000);
25-
}
39+
await Api.Instance.SetProviderAsync("process-test-flagd", flagdProvider).ConfigureAwait(false);
2640

27-
public FlagdStepDefinitionsProcess(ScenarioContext scenarioContext) : base(scenarioContext)
28-
{
29-
client = Api.Instance.GetClient("process-test-flagd");
41+
var client = Api.Instance.GetClient("process-test-flagd");
42+
43+
scenarioContext.Set(client, "Client");
44+
scenarioContext.Set(configuration, "Configuration");
3045
}
3146
}

test/OpenFeature.Contrib.Providers.Flagd.E2e.ProcessTest/Steps/TestHooks.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Threading.Tasks;
2+
using Microsoft.Extensions.Configuration;
23
using Reqnroll;
34

45
namespace OpenFeature.Contrib.Providers.Flagd.E2e.ProcessTest.Steps;
@@ -11,8 +12,17 @@ public class TestHooks
1112
[BeforeTestRun]
1213
public static async Task StartContainerAsync()
1314
{
14-
FlagdSyncTestBed = new FlagdSyncTestBedContainer();
15+
var configuration = new ConfigurationBuilder()
16+
.AddJsonFile("appsettings.json", optional: true)
17+
.AddEnvironmentVariables()
18+
.Build();
1519

20+
if (configuration["E2E"] != "true")
21+
{
22+
return;
23+
}
24+
25+
FlagdSyncTestBed = new FlagdSyncTestBedContainer();
1626
await FlagdSyncTestBed.Container.StartAsync().ConfigureAwait(false);
1727
}
1828

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"E2E": "true"
3+
}
Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,31 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<ItemGroup>
4-
<None
5-
Include="../../spec/specification/assets/gherkin/evaluation.feature"
6-
Link="../../../Features/%(Filename)%(Extension)"
7-
DestinationFolder="../../../Features/"
8-
CopyToOutputDirectory="PreserveNewest" />
4+
<None Include="../../spec/specification/assets/gherkin/evaluation.feature" Link="../../../Features/%(Filename)%(Extension)" DestinationFolder="../../../Features/" CopyToOutputDirectory="PreserveNewest" />
95
</ItemGroup>
106

117
<!-- TODO: add reconnect tests (remove exclusion) -->
128
<ItemGroup>
13-
<None
14-
Include="../../src/OpenFeature.Contrib.Providers.Flagd/flagd-testbed/gherkin/*.feature"
15-
Exclude="../../src/OpenFeature.Contrib.Providers.Flagd/flagd-testbed/gherkin/flagd-reconnect.feature"
16-
Link="../../../Features/%(Filename)%(Extension)"
17-
DestinationFolder="../../../Features/"
18-
CopyToOutputDirectory="PreserveNewest" />
9+
<None Include="../../src/OpenFeature.Contrib.Providers.Flagd/flagd-testbed/gherkin/*.feature" Exclude="../../src/OpenFeature.Contrib.Providers.Flagd/flagd-testbed/gherkin/flagd-reconnect.feature" Link="../../../Features/%(Filename)%(Extension)" DestinationFolder="../../../Features/" CopyToOutputDirectory="PreserveNewest" />
1910
</ItemGroup>
2011

2112
<ItemGroup>
22-
<ProjectReference
23-
Include="..\..\src\OpenFeature.Contrib.Providers.Flagd\OpenFeature.Contrib.Providers.Flagd.csproj" />
24-
<ProjectReference
25-
Include="..\OpenFeature.Contrib.Providers.Flagd.E2e.Common\OpenFeature.Contrib.Providers.Flagd.E2e.Common.csproj" />
13+
<ProjectReference Include="..\..\src\OpenFeature.Contrib.Providers.Flagd\OpenFeature.Contrib.Providers.Flagd.csproj" />
14+
<ProjectReference Include="..\OpenFeature.Contrib.Providers.Flagd.E2e.Common\OpenFeature.Contrib.Providers.Flagd.E2e.Common.csproj" />
2615
</ItemGroup>
2716

2817
<ItemGroup>
18+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
19+
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
20+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
2921
<PackageReference Include="Reqnroll.xUnit" Version="2.4.1" />
3022
<PackageReference Include="Testcontainers" Version="4.4.0" />
3123
</ItemGroup>
3224

25+
<ItemGroup>
26+
<None Update="appsettings.json">
27+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
28+
</None>
29+
</ItemGroup>
30+
3331
</Project>
Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
1+
using System.Threading.Tasks;
2+
using Microsoft.Extensions.Configuration;
13
using OpenFeature.Contrib.Providers.Flagd.E2e.Common;
24
using Reqnroll;
5+
using Xunit;
36

47
namespace OpenFeature.Contrib.Providers.Flagd.E2e.RpcTest.Steps;
58

69
[Binding, Scope(Feature = "Flag evaluation")]
710
public class EvaluationStepDefinitionsRpc : EvaluationStepDefinitionsBase
811
{
9-
static EvaluationStepDefinitionsRpc()
12+
public EvaluationStepDefinitionsRpc(ScenarioContext scenarioContext) : base(scenarioContext)
1013
{
14+
}
15+
16+
[BeforeScenario]
17+
public static async Task BeforeScenarioAsync(ScenarioContext scenarioContext, FeatureContext featureContext)
18+
{
19+
var configuration = new ConfigurationBuilder()
20+
.AddJsonFile("appsettings.json", optional: true)
21+
.AddEnvironmentVariables()
22+
.Build();
23+
24+
Skip.If(configuration["E2E"] != "true", "Skipping test as E2E tests are disabled, enable them by updating the appsettings.json.");
25+
1126
var host = TestHooks.FlagdTestBed.Container.Hostname;
1227
var port = TestHooks.FlagdTestBed.Container.GetMappedPublicPort(8013);
1328

@@ -18,11 +33,11 @@ static EvaluationStepDefinitionsRpc()
1833
.Build()
1934
);
2035

21-
Api.Instance.SetProviderAsync("rpc-test-evaluation", flagdProvider).Wait(5000);
22-
}
36+
await Api.Instance.SetProviderAsync("rpc-test-evaluation", flagdProvider).ConfigureAwait(false);
2337

24-
public EvaluationStepDefinitionsRpc(ScenarioContext scenarioContext) : base(scenarioContext)
25-
{
26-
client = Api.Instance.GetClient("rpc-test-evaluation");
38+
var client = Api.Instance.GetClient("rpc-test-evaluation");
39+
40+
scenarioContext.Set(client, "Client");
41+
scenarioContext.Set(configuration, "Configuration");
2742
}
2843
}

0 commit comments

Comments
 (0)