Skip to content

Commit 8e8c843

Browse files
authored
Feature/3 specflowplugin (#4)
* Implement plugin for SpecFlow 3.1 * Update README * Update README * Fix sonar issues * Update lifecycle * Fix Sonar issues * Fix build warning * Update lifecycly: remove SetCurrentTest method
1 parent 74e949e commit 8e8c843

17 files changed

+402
-42
lines changed

AqualityTracking.Integrations/AqualityTracking.Integrations.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AqualityTracking.Integratio
77
EndProject
88
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{38B81A9B-FA2A-425C-BEB5-40E69E0005CE}"
99
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AqualityTracking.SpecFlowPlugin", "src\AqualityTracking.SpecFlowPlugin\AqualityTracking.SpecFlowPlugin.csproj", "{80F5C607-A534-4629-9C5A-067522667610}"
11+
EndProject
1012
Global
1113
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1214
Debug|Any CPU = Debug|Any CPU
@@ -17,12 +19,17 @@ Global
1719
{0FE70831-5707-48AA-AD1E-8EC02E04C177}.Debug|Any CPU.Build.0 = Debug|Any CPU
1820
{0FE70831-5707-48AA-AD1E-8EC02E04C177}.Release|Any CPU.ActiveCfg = Release|Any CPU
1921
{0FE70831-5707-48AA-AD1E-8EC02E04C177}.Release|Any CPU.Build.0 = Release|Any CPU
22+
{80F5C607-A534-4629-9C5A-067522667610}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23+
{80F5C607-A534-4629-9C5A-067522667610}.Debug|Any CPU.Build.0 = Debug|Any CPU
24+
{80F5C607-A534-4629-9C5A-067522667610}.Release|Any CPU.ActiveCfg = Release|Any CPU
25+
{80F5C607-A534-4629-9C5A-067522667610}.Release|Any CPU.Build.0 = Release|Any CPU
2026
EndGlobalSection
2127
GlobalSection(SolutionProperties) = preSolution
2228
HideSolutionNode = FALSE
2329
EndGlobalSection
2430
GlobalSection(NestedProjects) = preSolution
2531
{0FE70831-5707-48AA-AD1E-8EC02E04C177} = {38B81A9B-FA2A-425C-BEB5-40E69E0005CE}
32+
{80F5C607-A534-4629-9C5A-067522667610} = {38B81A9B-FA2A-425C-BEB5-40E69E0005CE}
2633
EndGlobalSection
2734
GlobalSection(ExtensibilityGlobals) = postSolution
2835
SolutionGuid = {CC3B552A-F385-48E0-8496-DE13B78ECAED}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
11
using System;
2+
using System.Runtime.Serialization;
23

34
namespace AqualityTracking.Integrations.Core
45
{
6+
[Serializable]
57
public class AqualityException : Exception
68
{
9+
public AqualityException()
10+
{
11+
}
12+
713
public AqualityException(string message) : base(message)
814
{
915
}
16+
17+
public AqualityException(string message, Exception innerException) : base(message, innerException)
18+
{
19+
}
20+
21+
protected AqualityException(SerializationInfo info, StreamingContext context) : base(info, context)
22+
{
23+
}
1024
}
1125
}

AqualityTracking.Integrations/src/AqualityTracking.Integrations.Core/AqualityTracking.Integrations.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
</ItemGroup>
3333

3434
<ItemGroup>
35+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.4" />
3536
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.4" />
3637
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
3738
</ItemGroup>
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
using AqualityTracking.Integrations.Core;
2+
using AqualityTracking.Integrations.Core.Configuration;
3+
using AqualityTracking.Integrations.Core.Endpoints;
4+
using AqualityTracking.Integrations.Core.Models;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using System;
7+
using System.Collections.Generic;
8+
using System.Threading;
9+
10+
namespace AqualityTracking.SpecFlowPlugin
11+
{
12+
public class AqualityTrackingLifecycle
13+
{
14+
private static readonly object lockobj = new object();
15+
private static AqualityTrackingLifecycle instance;
16+
17+
private static Suite currentSuite;
18+
private static TestRun currentTestRun;
19+
20+
private readonly ThreadLocal<Test> currentTest = new ThreadLocal<Test>();
21+
private readonly ThreadLocal<TestResult> currentTestResult = new ThreadLocal<TestResult>();
22+
private readonly ThreadLocal<Action<Test>> updateCurrentTestAction = new ThreadLocal<Action<Test>>();
23+
24+
private readonly IConfiguration configuration;
25+
private readonly ISuiteEndpoints suiteEndpoints;
26+
private readonly ITestRunEndpoints testRunEndpoints;
27+
private readonly ITestEndpoints testEndpoints;
28+
private readonly ITestResultEndpoints testResultEndpoints;
29+
30+
private AqualityTrackingLifecycle()
31+
{
32+
var serviceCollection = new ServiceCollection();
33+
new Startup().ConfigureServices(serviceCollection);
34+
var provider = serviceCollection.BuildServiceProvider();
35+
36+
configuration = provider.GetRequiredService<IConfiguration>();
37+
suiteEndpoints = provider.GetRequiredService<ISuiteEndpoints>();
38+
testRunEndpoints = provider.GetRequiredService<ITestRunEndpoints>();
39+
testEndpoints = provider.GetRequiredService<ITestEndpoints>();
40+
testResultEndpoints = provider.GetRequiredService<ITestResultEndpoints>();
41+
}
42+
43+
public static AqualityTrackingLifecycle Instance
44+
{
45+
get
46+
{
47+
if (instance == null)
48+
{
49+
lock (lockobj)
50+
{
51+
instance = instance ?? new AqualityTrackingLifecycle();
52+
}
53+
}
54+
return instance;
55+
}
56+
}
57+
58+
private bool Enabled => configuration.Enabled;
59+
60+
public void StartTestRun()
61+
{
62+
if (Enabled)
63+
{
64+
var suite = suiteEndpoints.CreateSuite(configuration.SuiteName);
65+
var testRun = testRunEndpoints.StartTestRun((int)suite.Id, configuration.BuildName, configuration.Environment,
66+
configuration.Executor, configuration.CiBuild, configuration.Debug);
67+
SetCurrentSuite(suite);
68+
SetCurrentTestRun(testRun);
69+
}
70+
}
71+
72+
private static void SetCurrentSuite(Suite suite)
73+
{
74+
currentSuite = suite;
75+
}
76+
77+
private static void SetCurrentTestRun(TestRun testRun)
78+
{
79+
currentTestRun = testRun;
80+
}
81+
82+
public void StartTestExecution(string testName)
83+
{
84+
if (Enabled)
85+
{
86+
var desiredTest = new Test { Name = testName };
87+
updateCurrentTestAction.Value?.Invoke(desiredTest);
88+
89+
currentTest.Value = testEndpoints.CreateOrUpdateTest(desiredTest.Name, new List<Suite> { currentSuite });
90+
currentTestResult.Value = testResultEndpoints.StartTestResult((int)currentTestRun.Id, (int)currentTest.Value.Id);
91+
}
92+
}
93+
94+
public void AddAttachment(string filePath)
95+
{
96+
if (Enabled)
97+
{
98+
testResultEndpoints.AddAttachment((int)currentTestResult.Value.Id, filePath);
99+
}
100+
}
101+
102+
public void FinishTestExecution(FinalResultId finalResultId, string failReason)
103+
{
104+
if (Enabled)
105+
{
106+
testResultEndpoints.FinishTestResult((int)currentTestResult.Value.Id, finalResultId, failReason);
107+
}
108+
}
109+
110+
public void FinishTestRun()
111+
{
112+
if (Enabled)
113+
{
114+
testRunEndpoints.FinishTestRun((int)currentTestRun.Id);
115+
}
116+
}
117+
118+
public void UpdateCurrentTest(Action<Test> action)
119+
{
120+
updateCurrentTestAction.Value = action;
121+
}
122+
}
123+
}
Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using AqualityTracking.Integrations.Core.Utilities;
2-
using Newtonsoft.Json.Linq;
3-
using System.ComponentModel;
1+
using static AqualityTracking.Integrations.Core.Utilities.EnvironmentReader;
42

53
namespace AqualityTracking.Integrations.Core.Configuration
64
{
@@ -19,77 +17,62 @@ public class AqualityConfiguration : IConfiguration
1917

2018
public bool Enabled
2119
{
22-
get { return GetEnvValueOrDefault("aquality.enabled", enabled); }
20+
get { return GetValueOrDefault("aquality.enabled", enabled); }
2321
set { enabled = value; }
2422
}
2523

2624
public string Host
2725
{
28-
get { return GetEnvValueOrDefault("aquality.host", host); }
26+
get { return GetValueOrDefault("aquality.host", host); }
2927
set { host = value; }
3028
}
3129

3230
public string Token
3331
{
34-
get { return GetEnvValueOrDefault("aquality.token", token); }
32+
get { return GetValueOrDefault("aquality.token", token); }
3533
set { token = value; }
3634
}
3735

3836
public int ProjectId
3937
{
40-
get { return GetEnvValueOrDefault("aquality.projectId", projectId); }
38+
get { return GetValueOrDefault("aquality.projectId", projectId); }
4139
set { projectId = value; }
4240
}
4341

4442
public string Executor
4543
{
46-
get { return GetEnvValueOrDefault("aquality.executor", executor); }
44+
get { return GetValueOrDefault("aquality.executor", executor); }
4745
set { executor = value; }
4846
}
4947

5048
public string SuiteName
5149
{
52-
get { return GetEnvValueOrDefault("aquality.suiteName", suiteName); }
50+
get { return GetValueOrDefault("aquality.suiteName", suiteName); }
5351
set { suiteName = value; }
5452
}
5553

5654
public string BuildName
5755
{
58-
get { return GetEnvValueOrDefault("aquality.buildName", buildName); }
56+
get { return GetValueOrDefault("aquality.buildName", buildName); }
5957
set { buildName = value; }
6058
}
6159

6260
public string Environment
6361
{
64-
get { return GetEnvValueOrDefault("aquality.environment", environment); }
62+
get { return GetValueOrDefault("aquality.environment", environment); }
6563
set { environment = value; }
6664
}
6765

6866
public string CiBuild
6967
{
70-
get { return GetEnvValueOrDefault("aquality.ciBuild", ciBuild); }
68+
get { return GetValueOrDefault("aquality.ciBuild", ciBuild); }
7169
set { ciBuild = value; }
7270
}
7371

7472
public bool Debug
7573
{
76-
get { return GetEnvValueOrDefault("aquality.debug", debug); }
74+
get { return GetValueOrDefault("aquality.debug", debug); }
7775
set { debug = value; }
7876
}
79-
80-
private T GetEnvValueOrDefault<T>(string key, T defaultValue)
81-
{
82-
var envValue = EnvironmentReader.GetVariable(key);
83-
if (envValue != null)
84-
{
85-
return (T) TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(envValue);
86-
}
87-
return defaultValue;
88-
}
89-
90-
public static AqualityConfiguration ParseFromJson(string json)
91-
{
92-
return JObject.Parse(json)?.ToObject<AqualityConfiguration>();
93-
}
9477
}
9578
}

AqualityTracking.Integrations/src/AqualityTracking.Integrations.Core/Endpoints/ITestRunEndpoints.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
using AqualityTracking.Integrations.Core.Models;
2-
using System;
3-
using System.Collections.Generic;
4-
using System.Text;
52

63
namespace AqualityTracking.Integrations.Core.Endpoints
74
{

AqualityTracking.Integrations/src/AqualityTracking.Integrations.Core/Endpoints/Impl/AqualityTrackingEndpoints.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace AqualityTracking.Integrations.Core.Endpoints.Impl
66
{
77
public abstract class AqualityTrackingEndpoints
88
{
9-
public AqualityTrackingEndpoints(IConfiguration configuration, IHttpClient httpClient)
9+
protected AqualityTrackingEndpoints(IConfiguration configuration, IHttpClient httpClient)
1010
{
1111
Configuration = configuration;
1212
HttpClient = httpClient;

AqualityTracking.Integrations/src/AqualityTracking.Integrations.Core/FinalResultId.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace AqualityTracking.Integrations.Core
22
{
3-
public enum FinalResultId : int
3+
public enum FinalResultId
44
{
55
Failed = 1,
66
Passed = 2,

AqualityTracking.Integrations/src/AqualityTracking.Integrations.Core/Startup.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,34 @@
44
using AqualityTracking.Integrations.Core.Http;
55
using AqualityTracking.Integrations.Core.Utilities;
66
using Microsoft.Extensions.DependencyInjection;
7+
using Newtonsoft.Json.Linq;
8+
using System.IO;
79

810
namespace AqualityTracking.Integrations.Core
911
{
10-
public class Startup
12+
internal class Startup
1113
{
12-
public IServiceCollection ConfigureServices(IServiceCollection serviceCollection)
14+
internal void ConfigureServices(IServiceCollection serviceCollection)
1315
{
1416
serviceCollection.AddSingleton(getConfiguration());
1517
serviceCollection.AddScoped<IHttpClient, AqualityHttpClient>();
1618
serviceCollection.AddTransient<ISuiteEndpoints, SuiteEndpoints>();
1719
serviceCollection.AddTransient<ITestRunEndpoints, TestRunEndpoints>();
1820
serviceCollection.AddTransient<ITestEndpoints, TestEndpoints>();
1921
serviceCollection.AddTransient<ITestResultEndpoints, TestResultEndpoints>();
20-
return serviceCollection;
2122
}
2223

2324
private IConfiguration getConfiguration()
2425
{
25-
var jsonSettings = FileReader.ReadFromResources(AqualityConstants.SettingsFileName);
26-
return AqualityConfiguration.ParseFromJson(jsonSettings);
26+
try
27+
{
28+
var jsonSettings = FileReader.ReadFromResources(AqualityConstants.SettingsFileName);
29+
return JObject.Parse(jsonSettings)?.ToObject<AqualityConfiguration>();
30+
}
31+
catch (FileNotFoundException e)
32+
{
33+
throw new AqualityException($"Settings file `{AqualityConstants.SettingsFileName}` not found in `Resources` folder.", e);
34+
}
2735
}
2836
}
2937
}

AqualityTracking.Integrations/src/AqualityTracking.Integrations.Core/Utilities/EnvironmentReader.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.ComponentModel;
34
using System.Linq;
45

56
namespace AqualityTracking.Integrations.Core.Utilities
67
{
78
internal static class EnvironmentReader
89
{
10+
internal static T GetValueOrDefault<T>(string key, T defaultValue)
11+
{
12+
var envValue = GetVariable(key);
13+
if (envValue != null)
14+
{
15+
return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(envValue);
16+
}
17+
return defaultValue;
18+
}
19+
920
/// <summary>
1021
/// Gets value of environment variable by key.
1122
/// </summary>

0 commit comments

Comments
 (0)