From b554545b46b516eeeea6cc602b7ec27934c5a489 Mon Sep 17 00:00:00 2001 From: mg-diego Date: Sun, 20 Aug 2023 11:22:46 +0200 Subject: [PATCH 01/17] Add MongoDB engine --- TestWare.sln | 14 ++ .../Features/Database.feature | 25 ++++ samples/TestWare.Samples.MongoDB/Hook.cs | 114 ++++++++++++++ .../ImplicitUsings.cs | 3 + samples/TestWare.Samples.MongoDB/LifeCycle.cs | 36 +++++ .../Scripts/docker-compose.yml | 15 ++ .../Scripts/initialize-mongodb-docker.ps1 | 1 + .../Scripts/mongo-init.js | 12 ++ .../Seeder/DatabaseSeeder.cs | 27 ++++ .../DatabaseStepDefinitions.cs | 61 ++++++++ .../TestConfiguration.MongoDB.json | 14 ++ .../TestWare.Samples.MongoDB.csproj | 36 +++++ .../TestWare.Samples.MongoDB.csproj.user | 9 ++ .../TestWare.Engines.API/ApiManager.cs | 8 +- .../Configuration/Capabilities.cs | 8 + .../Factory/ClientFactory.cs | 11 ++ .../Factory/ConfigurationTags.cs | 7 + .../Factory/IMongoDbClient.cs | 34 +++++ .../Factory/MongoDbClient.cs | 140 ++++++++++++++++++ .../MongoDbManager.cs | 73 +++++++++ .../TestWare.Engines.MongoDB.csproj | 17 +++ 21 files changed, 664 insertions(+), 1 deletion(-) create mode 100644 samples/TestWare.Samples.MongoDB/Features/Database.feature create mode 100644 samples/TestWare.Samples.MongoDB/Hook.cs create mode 100644 samples/TestWare.Samples.MongoDB/ImplicitUsings.cs create mode 100644 samples/TestWare.Samples.MongoDB/LifeCycle.cs create mode 100644 samples/TestWare.Samples.MongoDB/Scripts/docker-compose.yml create mode 100644 samples/TestWare.Samples.MongoDB/Scripts/initialize-mongodb-docker.ps1 create mode 100644 samples/TestWare.Samples.MongoDB/Scripts/mongo-init.js create mode 100644 samples/TestWare.Samples.MongoDB/Seeder/DatabaseSeeder.cs create mode 100644 samples/TestWare.Samples.MongoDB/StepDefinitions/DatabaseStepDefinitions.cs create mode 100644 samples/TestWare.Samples.MongoDB/TestConfiguration.MongoDB.json create mode 100644 samples/TestWare.Samples.MongoDB/TestWare.Samples.MongoDB.csproj create mode 100644 samples/TestWare.Samples.MongoDB/TestWare.Samples.MongoDB.csproj.user create mode 100644 src/Engines/TestWare.Engines.MongoDB/Configuration/Capabilities.cs create mode 100644 src/Engines/TestWare.Engines.MongoDB/Factory/ClientFactory.cs create mode 100644 src/Engines/TestWare.Engines.MongoDB/Factory/ConfigurationTags.cs create mode 100644 src/Engines/TestWare.Engines.MongoDB/Factory/IMongoDbClient.cs create mode 100644 src/Engines/TestWare.Engines.MongoDB/Factory/MongoDbClient.cs create mode 100644 src/Engines/TestWare.Engines.MongoDB/MongoDbManager.cs create mode 100644 src/Engines/TestWare.Engines.MongoDB/TestWare.Engines.MongoDB.csproj diff --git a/TestWare.sln b/TestWare.sln index 3c7ff8cc..54e2ac0c 100644 --- a/TestWare.sln +++ b/TestWare.sln @@ -38,6 +38,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestWare.ExtentReport", "sr EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Reporting", "Reporting", "{DCCEF363-0EBE-46EA-B02B-CD59010626F6}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestWare.Engines.MongoDB", "src\Engines\TestWare.Engines.MongoDB\TestWare.Engines.MongoDB.csproj", "{4DFC2BE5-D3EF-4F39-AAD4-B8213DE92A11}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestWare.Samples.MongoDB", "samples\TestWare.Samples.MongoDB\TestWare.Samples.MongoDB.csproj", "{5378DE68-675E-440D-AAA9-7D3AF8AA680E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -84,6 +88,14 @@ Global {94025C6B-DF0D-4AC4-BBC5-A94A9FA3AB0A}.Debug|Any CPU.Build.0 = Debug|Any CPU {94025C6B-DF0D-4AC4-BBC5-A94A9FA3AB0A}.Release|Any CPU.ActiveCfg = Release|Any CPU {94025C6B-DF0D-4AC4-BBC5-A94A9FA3AB0A}.Release|Any CPU.Build.0 = Release|Any CPU + {4DFC2BE5-D3EF-4F39-AAD4-B8213DE92A11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DFC2BE5-D3EF-4F39-AAD4-B8213DE92A11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4DFC2BE5-D3EF-4F39-AAD4-B8213DE92A11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4DFC2BE5-D3EF-4F39-AAD4-B8213DE92A11}.Release|Any CPU.Build.0 = Release|Any CPU + {5378DE68-675E-440D-AAA9-7D3AF8AA680E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5378DE68-675E-440D-AAA9-7D3AF8AA680E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5378DE68-675E-440D-AAA9-7D3AF8AA680E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5378DE68-675E-440D-AAA9-7D3AF8AA680E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -102,6 +114,8 @@ Global {71120454-DD7A-484C-93F2-699B4C363297} = {58B1446D-98A3-46A2-A668-305F0170B39F} {94025C6B-DF0D-4AC4-BBC5-A94A9FA3AB0A} = {DCCEF363-0EBE-46EA-B02B-CD59010626F6} {DCCEF363-0EBE-46EA-B02B-CD59010626F6} = {4678C707-68DB-4E06-9184-A07FB398832C} + {4DFC2BE5-D3EF-4F39-AAD4-B8213DE92A11} = {A2E4E1F7-CB61-48DC-AA38-A74F7DC74CA2} + {5378DE68-675E-440D-AAA9-7D3AF8AA680E} = {58B1446D-98A3-46A2-A668-305F0170B39F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4F88CB24-23C8-4E0E-8B83-29023C1642B8} diff --git a/samples/TestWare.Samples.MongoDB/Features/Database.feature b/samples/TestWare.Samples.MongoDB/Features/Database.feature new file mode 100644 index 00000000..a381f355 --- /dev/null +++ b/samples/TestWare.Samples.MongoDB/Features/Database.feature @@ -0,0 +1,25 @@ +@MongoDB +Feature: Database + + +Scenario: Insert at database + When the following document is inserted in 'collection-example' collection at 'database-example' database + | NAME | + | Didac | + Then the following document is saved in 'collection-example' collection at 'database-example' database + | NAME | + | Didac | + + +Scenario: Delete at database + Given the following document is saved in 'collection-example' collection at 'database-example' database + | NAME | + | Diego | + When the following document is deleted in 'collection-example' collection at 'database-example' database + | NAME | + | Diego | + Then no documents are saved in 'collection-example' collection at 'database-example' database with values + | NAME | + | Diego | + + diff --git a/samples/TestWare.Samples.MongoDB/Hook.cs b/samples/TestWare.Samples.MongoDB/Hook.cs new file mode 100644 index 00000000..793e5a2f --- /dev/null +++ b/samples/TestWare.Samples.MongoDB/Hook.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using TestWare.Reporting.ExtentReport; +using TestWare.Samples.MongoDB.Seeder; + +namespace TestWare.Samples.MongoDB; + +[Binding] +public sealed class Hook +{ + private readonly TestContext _testContext; + private int _stepCounter; + private static readonly LifeCycle _lifeCycle = new(); + private static ExtentReport _testReport; + + public Hook(TestContext testContext) + { + _testContext = testContext; + } + + [BeforeFeature] + public static void BeforeFeature(FeatureContext featureContext) + { + var name = featureContext.FeatureInfo.Title; + var tags = featureContext.FeatureInfo.Tags; + + _lifeCycle.BeginTestSuite(name); + _testReport.CreateFeature(name, tags); + } + + [AfterFeature] + public static void AfterFeature(FeatureContext featureContext) + { + _lifeCycle.EndTestSuite(); + } + + [BeforeScenario] + public void BeforeScenario(FeatureContext featureContext, ScenarioContext scenarioContext) + { + var name = scenarioContext.ScenarioInfo.Arguments.Count > 0 + ? $"{DateTime.UtcNow.ToString("yyy-MM-dd HH-mm-ss", CultureInfo.InvariantCulture)} - {scenarioContext.ScenarioInfo.Title}" + : scenarioContext.ScenarioInfo.Title; + + var description = scenarioContext.ScenarioInfo.Description ?? ""; + var scenarioTags = scenarioContext.ScenarioInfo.Tags; + _testReport.CreateTestCase(name, description, scenarioTags); + + _testContext.WriteLine("----------------------------------------- \r\n"); + _testContext.WriteLine($"Feature: {featureContext.FeatureInfo.Title}"); + _testContext.WriteLine($" Scenario: {scenarioContext.ScenarioInfo.Title} \r\n"); + + _stepCounter = 1; + var tags = GetTags(featureContext, scenarioContext); + _lifeCycle.BeginTestCase(name, tags); + + var databaseSeeder = new DatabaseSeeder(); + databaseSeeder.InitializeDatabase(); + } + + [AfterScenario] + public void AfterScenario() + { + _testReport.SetTestcaseOutcome(_testContext.CurrentTestOutcome); + _lifeCycle.EndTestCase(); + } + + [BeforeTestRun] + public static void BeforeTestRun() + { + _lifeCycle.BeginTestExecution(); + _testReport = new ExtentReport(_lifeCycle.GetCurrentResultsDirectory()); + } + + [AfterTestRun] + public static void AfterTestRun() + { + _lifeCycle.EndTestExecution(); + _testReport.CreateTestReportFile(); + } + + [BeforeStep] + public void BeforeStep(ScenarioContext scenarioContext) + { + var name = scenarioContext.CurrentScenarioBlock.ToString(); + var description = scenarioContext.StepContext.StepInfo.Text; + _testReport.CreateStep(name, description); + + var stepId = $"{_stepCounter:00} {description}"; + _stepCounter++; + _lifeCycle.BeginTestStep(stepId); + } + + [AfterStep] + public void AfterStep(ScenarioContext scenarioContext) + { + _lifeCycle.EndTestStep(); + var evidencesPath = _lifeCycle.GetStepEvidences(); + + foreach (var evidence in evidencesPath) + { + _testReport.AddScreenshotToStep(evidence); + _testContext.AddResultFile(evidence); + } + } + + private static List GetTags(FeatureContext featureContext, ScenarioContext scenarioContext) + { + var tags = featureContext.FeatureInfo.Tags.ToList(); + tags.AddRange(scenarioContext.ScenarioInfo.Tags.ToList()); + return tags; + } +} diff --git a/samples/TestWare.Samples.MongoDB/ImplicitUsings.cs b/samples/TestWare.Samples.MongoDB/ImplicitUsings.cs new file mode 100644 index 00000000..8022d597 --- /dev/null +++ b/samples/TestWare.Samples.MongoDB/ImplicitUsings.cs @@ -0,0 +1,3 @@ +global using FluentAssertions; +global using Microsoft.VisualStudio.TestTools.UnitTesting; +global using TechTalk.SpecFlow; diff --git a/samples/TestWare.Samples.MongoDB/LifeCycle.cs b/samples/TestWare.Samples.MongoDB/LifeCycle.cs new file mode 100644 index 00000000..bc4eadc4 --- /dev/null +++ b/samples/TestWare.Samples.MongoDB/LifeCycle.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Reflection; +using TestWare.Core; +using TestWare.Core.Configuration; +using TestWare.Core.Interfaces; +using TestWare.Engines.MongoDB; + +namespace TestWare.Samples.MongoDB; + +internal class LifeCycle : AutomationLifeCycleBase +{ + protected override IEnumerable GetTestWareComponentAssemblies() + { + IEnumerable assemblies = new[] + { + typeof(Hook).Assembly + }; + + return assemblies; + } + + protected override IEnumerable GetTestWareEngines() + { + IEnumerable engines = new[] + { + new MongoDbManager() + }; + + return engines; + } + + protected override TestConfiguration GetConfiguration() + { + return ConfigurationManager.ReadConfigurationFile("TestConfiguration.MongoDB.json"); + } +} diff --git a/samples/TestWare.Samples.MongoDB/Scripts/docker-compose.yml b/samples/TestWare.Samples.MongoDB/Scripts/docker-compose.yml new file mode 100644 index 00000000..f022887d --- /dev/null +++ b/samples/TestWare.Samples.MongoDB/Scripts/docker-compose.yml @@ -0,0 +1,15 @@ +version: '3.7' + +services: + mongodb: + image: mongo:latest + container_name: mongodb + restart: always + environment: + MONGO_INITDB_ROOT_USERNAME: guest + MONGO_INITDB_ROOT_PASSWORD: guest + MONGO_INITDB_DATABASE: admin + ports: + - 27017:27017 + volumes: + - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro \ No newline at end of file diff --git a/samples/TestWare.Samples.MongoDB/Scripts/initialize-mongodb-docker.ps1 b/samples/TestWare.Samples.MongoDB/Scripts/initialize-mongodb-docker.ps1 new file mode 100644 index 00000000..453dde20 --- /dev/null +++ b/samples/TestWare.Samples.MongoDB/Scripts/initialize-mongodb-docker.ps1 @@ -0,0 +1 @@ +docker-compose up --build -d mongodb \ No newline at end of file diff --git a/samples/TestWare.Samples.MongoDB/Scripts/mongo-init.js b/samples/TestWare.Samples.MongoDB/Scripts/mongo-init.js new file mode 100644 index 00000000..6471b784 --- /dev/null +++ b/samples/TestWare.Samples.MongoDB/Scripts/mongo-init.js @@ -0,0 +1,12 @@ +db.createUser( + { + user: "guest", + pwd: "guest", + roles: [ + { + role: "readWrite", + db: "database-example" + } + ] + } +); \ No newline at end of file diff --git a/samples/TestWare.Samples.MongoDB/Seeder/DatabaseSeeder.cs b/samples/TestWare.Samples.MongoDB/Seeder/DatabaseSeeder.cs new file mode 100644 index 00000000..d1440145 --- /dev/null +++ b/samples/TestWare.Samples.MongoDB/Seeder/DatabaseSeeder.cs @@ -0,0 +1,27 @@ +using MongoDB.Bson; +using TestWare.Core; +using TestWare.Engines.MongoDB.Factory; + +namespace TestWare.Samples.MongoDB.Seeder; + +internal class DatabaseSeeder +{ + private readonly IMongoDbClient _mongoDbClient; + private const string DATABASE_NAME = "database-example"; + private const string COLLECTION_NAME = "collection-example"; + + public DatabaseSeeder() + { + _mongoDbClient = ContainerManager.GetTestWareComponent(); + } + + public void InitializeDatabase() + { + _mongoDbClient.DropDatabase(DATABASE_NAME); + + _mongoDbClient.CreateDatabase(DATABASE_NAME); + _mongoDbClient.CreateCollection(DATABASE_NAME, COLLECTION_NAME); + + _mongoDbClient.InsertOne(new BsonDocument("name", "Diego"), DATABASE_NAME, COLLECTION_NAME); + } +} diff --git a/samples/TestWare.Samples.MongoDB/StepDefinitions/DatabaseStepDefinitions.cs b/samples/TestWare.Samples.MongoDB/StepDefinitions/DatabaseStepDefinitions.cs new file mode 100644 index 00000000..ff800afe --- /dev/null +++ b/samples/TestWare.Samples.MongoDB/StepDefinitions/DatabaseStepDefinitions.cs @@ -0,0 +1,61 @@ +using FluentAssertions.Execution; +using MongoDB.Bson; +using TestWare.Core; +using TestWare.Engines.MongoDB.Factory; + +namespace TestWare.Samples.MongoDB.StepDefinitions; + +[Binding] +public class DatabaseStepDefinitions +{ + private readonly IMongoDbClient _mongoDbClient; + + public DatabaseStepDefinitions() + { + _mongoDbClient = ContainerManager.GetTestWareComponent(); + } + + [When(@"the following document is inserted in '([^']*)' collection at '([^']*)' database")] + public void TheFollowingDocumentIsInsertedInCollectionAtDatabase(string collectionName, string databaseName, Table table) + { + var value = table.Rows[0]["NAME"].ToString(); + + _mongoDbClient.InsertOne(new BsonDocument("name", value), databaseName, collectionName); + } + + [When(@"the following document is deleted in '([^']*)' collection at '([^']*)' database")] + public void TheFollowingDocumentIsDeletedInCollectionAtDatabase(string collectionName, string databaseName, Table table) + { + var value = table.Rows[0]["NAME"].ToString(); + + _mongoDbClient.DeleteOne(new BsonDocument("name", value), databaseName, collectionName); + } + + + [Given(@"the following document is saved in '([^']*)' collection at '([^']*)' database")] + [Then(@"the following document is saved in '([^']*)' collection at '([^']*)' database")] + public void TheFollowingDocumentIsSavedInCollectionAtDatabase(string collectionName, string databaseName, Table table) + { + var value = table.Rows[0]["NAME"].ToString(); + + var result = _mongoDbClient.Find(new BsonDocument("name", value), databaseName, collectionName).Result; + + using (new AssertionScope()) + { + result.Should().NotBeNull(); + result.Count.Should().Be(1); + result[0].GetValue("name").RawValue.Should().Be(value); + } + } + + [Then(@"no documents are saved in '([^']*)' collection at '([^']*)' database with values")] + public void ThenNoDocumentsAreSavedInCollectionAtDatabaseWithValues(string collectionName, string databaseName, Table table) + { + var value = table.Rows[0]["NAME"].ToString(); + + var result = _mongoDbClient.Find(new BsonDocument("name", value), databaseName, collectionName).Result; + + result.Count.Should().Be(0); + } + +} diff --git a/samples/TestWare.Samples.MongoDB/TestConfiguration.MongoDB.json b/samples/TestWare.Samples.MongoDB/TestConfiguration.MongoDB.json new file mode 100644 index 00000000..17840e62 --- /dev/null +++ b/samples/TestWare.Samples.MongoDB/TestConfiguration.MongoDB.json @@ -0,0 +1,14 @@ +{ + "Configurations": [ + { + "Tag": "MongoDB", + "Capabilities": [ + { + "Name": "MongoDB", + "ConnectionString": "mongodb://guest:guest@localhost:27017/" + } + ] + } + ], + "TestResultPath": "C:\\workspace\\ERNI\\results\\" +} \ No newline at end of file diff --git a/samples/TestWare.Samples.MongoDB/TestWare.Samples.MongoDB.csproj b/samples/TestWare.Samples.MongoDB/TestWare.Samples.MongoDB.csproj new file mode 100644 index 00000000..5f7c44b4 --- /dev/null +++ b/samples/TestWare.Samples.MongoDB/TestWare.Samples.MongoDB.csproj @@ -0,0 +1,36 @@ + + + + net6.0 + enable + + false + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + + diff --git a/samples/TestWare.Samples.MongoDB/TestWare.Samples.MongoDB.csproj.user b/samples/TestWare.Samples.MongoDB/TestWare.Samples.MongoDB.csproj.user new file mode 100644 index 00000000..7421e458 --- /dev/null +++ b/samples/TestWare.Samples.MongoDB/TestWare.Samples.MongoDB.csproj.user @@ -0,0 +1,9 @@ + + + + + + Code + + + \ No newline at end of file diff --git a/src/Engines/TestWare.Engines.API/ApiManager.cs b/src/Engines/TestWare.Engines.API/ApiManager.cs index 19f44d44..aafa0bbd 100644 --- a/src/Engines/TestWare.Engines.API/ApiManager.cs +++ b/src/Engines/TestWare.Engines.API/ApiManager.cs @@ -1,5 +1,6 @@ using Autofac; using System.Linq; +using System.Text.Encodings.Web; using System.Text.Json; using TestWare.Core; using TestWare.Core.Configuration; @@ -70,7 +71,12 @@ public string CollectEvidence(string destinationPath, string evidenceName) { var responses = apiClient.GetRestResponses(); var instanceName = ContainerManager.GetNameFromInstance(apiClient); - var evidenceData = JsonSerializer.Serialize(responses); + var serializeOptions = new JsonSerializerOptions + { + WriteIndented = true, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + }; + var evidenceData = JsonSerializer.Serialize(responses, serializeOptions); var evidencePath = Path.Combine(destinationPath, $"{evidenceName} - {instanceName}.json"); File.WriteAllText(evidencePath, evidenceData); apiClient.ClearResponseQueue(); diff --git a/src/Engines/TestWare.Engines.MongoDB/Configuration/Capabilities.cs b/src/Engines/TestWare.Engines.MongoDB/Configuration/Capabilities.cs new file mode 100644 index 00000000..34563ada --- /dev/null +++ b/src/Engines/TestWare.Engines.MongoDB/Configuration/Capabilities.cs @@ -0,0 +1,8 @@ +namespace TestWare.Engines.MongoDB.Configuration; + +internal class Capabilities +{ + public string Name { get; set; } + + public string ConnectionString { get; set; } +} diff --git a/src/Engines/TestWare.Engines.MongoDB/Factory/ClientFactory.cs b/src/Engines/TestWare.Engines.MongoDB/Factory/ClientFactory.cs new file mode 100644 index 00000000..4cad0439 --- /dev/null +++ b/src/Engines/TestWare.Engines.MongoDB/Factory/ClientFactory.cs @@ -0,0 +1,11 @@ +using TestWare.Engines.MongoDB.Configuration; + +namespace TestWare.Engines.MongoDB.Factory; + +internal class ClientFactory +{ + public static IMongoDbClient Create(Capabilities capabilities) + { + return new MongoDbClient(capabilities.ConnectionString); + } +} diff --git a/src/Engines/TestWare.Engines.MongoDB/Factory/ConfigurationTags.cs b/src/Engines/TestWare.Engines.MongoDB/Factory/ConfigurationTags.cs new file mode 100644 index 00000000..942eca07 --- /dev/null +++ b/src/Engines/TestWare.Engines.MongoDB/Factory/ConfigurationTags.cs @@ -0,0 +1,7 @@ +namespace TestWare.Engines.MongoDB.Factory; + +public enum ConfigurationTags +{ + none = 0, + mongodb = 1 +} diff --git a/src/Engines/TestWare.Engines.MongoDB/Factory/IMongoDbClient.cs b/src/Engines/TestWare.Engines.MongoDB/Factory/IMongoDbClient.cs new file mode 100644 index 00000000..440571a2 --- /dev/null +++ b/src/Engines/TestWare.Engines.MongoDB/Factory/IMongoDbClient.cs @@ -0,0 +1,34 @@ +using MongoDB.Bson; + +namespace TestWare.Engines.MongoDB.Factory; + +public interface IMongoDbClient +{ + void CreateDatabase(string databaseName); + + void DropDatabase(string databaseName); + + void CreateCollection(string databaseName, string collectionName); + + void DropCollection(string databaseName, string collectionName); + + void InsertOne(BsonDocument document, string databaseName, string collectionName); + + void InsertMany(IEnumerable documentList, string databaseName, string collectionName); + + void UpdateOne(BsonDocument document, string databaseName, string collectionName); + + void UpdateMany(BsonDocument document, string databaseName, string collectionName); + + void DeleteOne(BsonDocument document, string databaseName, string collectionName); + + void DeleteMany(BsonDocument document, string databaseName, string collectionName); + + Task Count(BsonDocument document, string databaseName, string collectionName); + + Task> Find(BsonDocument document, string databaseName, string collectionName); + + List GetClientLogs(); + + void ClearClientLogs(); +} diff --git a/src/Engines/TestWare.Engines.MongoDB/Factory/MongoDbClient.cs b/src/Engines/TestWare.Engines.MongoDB/Factory/MongoDbClient.cs new file mode 100644 index 00000000..f78fcf22 --- /dev/null +++ b/src/Engines/TestWare.Engines.MongoDB/Factory/MongoDbClient.cs @@ -0,0 +1,140 @@ +using MongoDB.Bson; +using MongoDB.Driver; +using MongoDB.Driver.Core.Events; + +namespace TestWare.Engines.MongoDB.Factory; + +internal class MongoDbClient : MongoClient, IMongoDbClient +{ + private readonly MongoClient mongoClient; + + private List clientLogs; + + public MongoDbClient(string connectionString) + { + clientLogs = new List(); + var mongoConnectionUrl = new MongoUrl(connectionString); + var mongoClientSettings = MongoClientSettings.FromUrl(mongoConnectionUrl); + + mongoClientSettings.ClusterConfigurator = cb => + { + cb.Subscribe(e => + { + clientLogs.Add($"{e.CommandName} - {e.Command.ToJson()}"); + }); + }; + + mongoClient = new MongoClient(mongoClientSettings); + } + + public void CreateDatabase(string databaseName) + { + GetDatabase(databaseName); + } + + public void DropDatabase(string databaseName) + { + mongoClient.DropDatabase(databaseName); + } + + public void CreateCollection(string databaseName, string collectionName) + { + var database = GetDatabase(databaseName); + database.CreateCollection(collectionName); + } + + public void DropCollection(string databaseName, string collectionName) + { + var database = GetDatabase(databaseName); + database.DropCollection(collectionName); + } + + public async void InsertOne(BsonDocument document, string databaseName, string collectionName) + { + var database = GetDatabase(databaseName); + var collection = GetCollection(database, collectionName); + + await collection.InsertOneAsync(document); + } + + public async void InsertMany(IEnumerable documentList, string databaseName, string collectionName) + { + var database = GetDatabase(databaseName); + var collection = GetCollection(database, collectionName); + + await collection.InsertManyAsync(documentList); + } + + public async void UpdateOne(BsonDocument document, string databaseName, string collectionName) + { + var database = GetDatabase(databaseName); + var collection = GetCollection(database, collectionName); + + throw new NotImplementedException(); + } + + public async void UpdateMany(BsonDocument document, string databaseName, string collectionName) + { + var database = GetDatabase(databaseName); + var collection = GetCollection(database, collectionName); + + throw new NotImplementedException(); + } + + public async void DeleteOne(BsonDocument document, string databaseName, string collectionName) + { + var database = GetDatabase(databaseName); + var collection = GetCollection(database, collectionName); + + await collection.DeleteOneAsync(document); + } + + public async void DeleteMany(BsonDocument document, string databaseName, string collectionName) + { + var database = GetDatabase(databaseName); + var collection = GetCollection(database, collectionName); + + await collection.DeleteManyAsync(document); + } + + public async Task Count(BsonDocument document, string databaseName, string collectionName) + { + var database = GetDatabase(databaseName); + var collection = GetCollection(database, collectionName); + + var count = await collection.CountDocumentsAsync(document); + + return count; + } + + public async Task> Find(BsonDocument document, string databaseName, string collectionName) + { + var database = GetDatabase(databaseName); + var collection = GetCollection(database, collectionName); + + var list = await collection.Find(document).ToListAsync(); + + return list; + } + + public List GetClientLogs() + { + return clientLogs; + } + + public void ClearClientLogs() + { + clientLogs = new List(); + } + + private IMongoDatabase GetDatabase(string databaseName) + { + return mongoClient.GetDatabase(databaseName); + } + + private static IMongoCollection GetCollection(IMongoDatabase database, string collectionName) + { + return database.GetCollection(collectionName); + } +} + diff --git a/src/Engines/TestWare.Engines.MongoDB/MongoDbManager.cs b/src/Engines/TestWare.Engines.MongoDB/MongoDbManager.cs new file mode 100644 index 00000000..e0b498aa --- /dev/null +++ b/src/Engines/TestWare.Engines.MongoDB/MongoDbManager.cs @@ -0,0 +1,73 @@ +using Autofac; +using System.Text; +using System.Text.Encodings.Web; +using System.Text.Json; +using TestWare.Core; +using TestWare.Core.Configuration; +using TestWare.Core.Interfaces; +using TestWare.Engines.MongoDB.Configuration; +using TestWare.Engines.MongoDB.Factory; + +namespace TestWare.Engines.MongoDB; + +public class MongoDbManager : EngineManagerBase, IEngineManager +{ + private const string _name = "MongoDb"; + + private static void RegisterSingle(IEnumerable tags, TestConfiguration testConfiguration) + { + var configName = Enum.GetName(ConfigurationTags.mongodb).ToUpperInvariant(); + var capabilities = ConfigurationManager.GetCapabilities(testConfiguration, configName); + var singleCapability = capabilities.FirstOrDefault(x => tags.Contains(x.Name.ToUpperInvariant())); + if (!ContainerManager.ExistsType(singleCapability.GetType())) + { + var driver = ClientFactory.Create(singleCapability); + ContainerManager.RegisterType(singleCapability.Name, driver); + } + } + + public string CollectEvidence(string destinationPath, string evidenceName) + { + var mongoDbClients = ContainerManager.Container.Resolve>(); + + foreach (var mongoDbClient in mongoDbClients) + { + var responses = mongoDbClient.GetClientLogs(); + var instanceName = ContainerManager.GetNameFromInstance(mongoDbClient); + var serializeOptions = new JsonSerializerOptions + { + WriteIndented = true, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + }; + var evidenceData = JsonSerializer.Serialize(responses, serializeOptions); + var evidencePath = Path.Combine(destinationPath, $"{evidenceName} - {instanceName}.json"); + File.WriteAllText(evidencePath, evidenceData, Encoding.UTF8); + mongoDbClient.ClearClientLogs(); + } + + return destinationPath; + } + + public void Destroy() + { + //Do nothing, the client handles it automatically + } + + public string GetEngineName() + { + return _name; + } + + public void Initialize(IEnumerable tags, TestConfiguration testConfiguration) + { + var normalizedTags = tags.Select(x => x.ToUpperInvariant()).ToArray(); + var foundConfiguration = ConfigurationManager.GetValidConfiguration(normalizedTags); + + switch (foundConfiguration) + { + case ConfigurationTags.mongodb: + RegisterSingle(normalizedTags, testConfiguration); + break; + } + } +} diff --git a/src/Engines/TestWare.Engines.MongoDB/TestWare.Engines.MongoDB.csproj b/src/Engines/TestWare.Engines.MongoDB/TestWare.Engines.MongoDB.csproj new file mode 100644 index 00000000..35e71620 --- /dev/null +++ b/src/Engines/TestWare.Engines.MongoDB/TestWare.Engines.MongoDB.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + From 0193d5047fa5f691731cb1f4b11ecc8c4c17d204 Mon Sep 17 00:00:00 2001 From: mg-diego Date: Fri, 6 Oct 2023 18:02:34 +0200 Subject: [PATCH 02/17] Solve PR comments --- samples/TestWare.Samples.MongoDB/Hook.cs | 2 +- .../StepDefinitions/DatabaseStepDefinitions.cs | 2 +- .../Configuration/Capabilities.cs | 4 ++-- .../TestWare.Engines.MongoDB/Factory/MongoDbClient.cs | 8 ++++---- src/Engines/TestWare.Engines.MongoDB/MongoDbManager.cs | 9 ++++++--- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/samples/TestWare.Samples.MongoDB/Hook.cs b/samples/TestWare.Samples.MongoDB/Hook.cs index 793e5a2f..742a1318 100644 --- a/samples/TestWare.Samples.MongoDB/Hook.cs +++ b/samples/TestWare.Samples.MongoDB/Hook.cs @@ -13,7 +13,7 @@ public sealed class Hook private readonly TestContext _testContext; private int _stepCounter; private static readonly LifeCycle _lifeCycle = new(); - private static ExtentReport _testReport; + private static ExtentReport? _testReport; public Hook(TestContext testContext) { diff --git a/samples/TestWare.Samples.MongoDB/StepDefinitions/DatabaseStepDefinitions.cs b/samples/TestWare.Samples.MongoDB/StepDefinitions/DatabaseStepDefinitions.cs index ff800afe..af354e32 100644 --- a/samples/TestWare.Samples.MongoDB/StepDefinitions/DatabaseStepDefinitions.cs +++ b/samples/TestWare.Samples.MongoDB/StepDefinitions/DatabaseStepDefinitions.cs @@ -44,7 +44,7 @@ public void TheFollowingDocumentIsSavedInCollectionAtDatabase(string collectionN { result.Should().NotBeNull(); result.Count.Should().Be(1); - result[0].GetValue("name").RawValue.Should().Be(value); + BsonTypeMapper.MapToDotNetValue(result[0].GetValue("name")).ToString().Should().Be(value); } } diff --git a/src/Engines/TestWare.Engines.MongoDB/Configuration/Capabilities.cs b/src/Engines/TestWare.Engines.MongoDB/Configuration/Capabilities.cs index 34563ada..9f91e96f 100644 --- a/src/Engines/TestWare.Engines.MongoDB/Configuration/Capabilities.cs +++ b/src/Engines/TestWare.Engines.MongoDB/Configuration/Capabilities.cs @@ -2,7 +2,7 @@ internal class Capabilities { - public string Name { get; set; } + public string? Name { get; set; } - public string ConnectionString { get; set; } + public string? ConnectionString { get; set; } } diff --git a/src/Engines/TestWare.Engines.MongoDB/Factory/MongoDbClient.cs b/src/Engines/TestWare.Engines.MongoDB/Factory/MongoDbClient.cs index f78fcf22..9b9fcf44 100644 --- a/src/Engines/TestWare.Engines.MongoDB/Factory/MongoDbClient.cs +++ b/src/Engines/TestWare.Engines.MongoDB/Factory/MongoDbClient.cs @@ -65,20 +65,20 @@ public async void InsertMany(IEnumerable documentList, string data await collection.InsertManyAsync(documentList); } - public async void UpdateOne(BsonDocument document, string databaseName, string collectionName) + public void UpdateOne(BsonDocument document, string databaseName, string collectionName) { var database = GetDatabase(databaseName); var collection = GetCollection(database, collectionName); - throw new NotImplementedException(); + throw new NotImplementedException("Pending to implement"); } - public async void UpdateMany(BsonDocument document, string databaseName, string collectionName) + public void UpdateMany(BsonDocument document, string databaseName, string collectionName) { var database = GetDatabase(databaseName); var collection = GetCollection(database, collectionName); - throw new NotImplementedException(); + throw new NotImplementedException("Pending to implement"); } public async void DeleteOne(BsonDocument document, string databaseName, string collectionName) diff --git a/src/Engines/TestWare.Engines.MongoDB/MongoDbManager.cs b/src/Engines/TestWare.Engines.MongoDB/MongoDbManager.cs index e0b498aa..bbba2305 100644 --- a/src/Engines/TestWare.Engines.MongoDB/MongoDbManager.cs +++ b/src/Engines/TestWare.Engines.MongoDB/MongoDbManager.cs @@ -16,14 +16,17 @@ public class MongoDbManager : EngineManagerBase, IEngineManager private static void RegisterSingle(IEnumerable tags, TestConfiguration testConfiguration) { - var configName = Enum.GetName(ConfigurationTags.mongodb).ToUpperInvariant(); + var configName = Enum.GetName(ConfigurationTags.mongodb)?.ToUpperInvariant(); var capabilities = ConfigurationManager.GetCapabilities(testConfiguration, configName); - var singleCapability = capabilities.FirstOrDefault(x => tags.Contains(x.Name.ToUpperInvariant())); - if (!ContainerManager.ExistsType(singleCapability.GetType())) + var singleCapability = capabilities.FirstOrDefault(x => tags.Contains(x?.Name?.ToUpperInvariant())); + if (singleCapability != null && !ContainerManager.ExistsType(singleCapability.GetType())) { var driver = ClientFactory.Create(singleCapability); ContainerManager.RegisterType(singleCapability.Name, driver); } + else { + throw new NullReferenceException("No suitable capability found."); + } } public string CollectEvidence(string destinationPath, string evidenceName) From 3ee1e31137e5b44d7da1505b9f608908c2822560 Mon Sep 17 00:00:00 2001 From: mg-diego Date: Fri, 6 Oct 2023 18:14:26 +0200 Subject: [PATCH 03/17] Solve PR comments --- samples/TestWare.Samples.MongoDB/Hook.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/TestWare.Samples.MongoDB/Hook.cs b/samples/TestWare.Samples.MongoDB/Hook.cs index 742a1318..1f81171b 100644 --- a/samples/TestWare.Samples.MongoDB/Hook.cs +++ b/samples/TestWare.Samples.MongoDB/Hook.cs @@ -27,7 +27,7 @@ public static void BeforeFeature(FeatureContext featureContext) var tags = featureContext.FeatureInfo.Tags; _lifeCycle.BeginTestSuite(name); - _testReport.CreateFeature(name, tags); + _testReport?.CreateFeature(name, tags); } [AfterFeature] @@ -45,7 +45,7 @@ public void BeforeScenario(FeatureContext featureContext, ScenarioContext scenar var description = scenarioContext.ScenarioInfo.Description ?? ""; var scenarioTags = scenarioContext.ScenarioInfo.Tags; - _testReport.CreateTestCase(name, description, scenarioTags); + _testReport?.CreateTestCase(name, description, scenarioTags); _testContext.WriteLine("----------------------------------------- \r\n"); _testContext.WriteLine($"Feature: {featureContext.FeatureInfo.Title}"); @@ -62,7 +62,7 @@ public void BeforeScenario(FeatureContext featureContext, ScenarioContext scenar [AfterScenario] public void AfterScenario() { - _testReport.SetTestcaseOutcome(_testContext.CurrentTestOutcome); + _testReport?.SetTestcaseOutcome(_testContext.CurrentTestOutcome); _lifeCycle.EndTestCase(); } @@ -77,7 +77,7 @@ public static void BeforeTestRun() public static void AfterTestRun() { _lifeCycle.EndTestExecution(); - _testReport.CreateTestReportFile(); + _testReport?.CreateTestReportFile(); } [BeforeStep] @@ -85,7 +85,7 @@ public void BeforeStep(ScenarioContext scenarioContext) { var name = scenarioContext.CurrentScenarioBlock.ToString(); var description = scenarioContext.StepContext.StepInfo.Text; - _testReport.CreateStep(name, description); + _testReport?.CreateStep(name, description); var stepId = $"{_stepCounter:00} {description}"; _stepCounter++; @@ -100,7 +100,7 @@ public void AfterStep(ScenarioContext scenarioContext) foreach (var evidence in evidencesPath) { - _testReport.AddScreenshotToStep(evidence); + _testReport?.AddScreenshotToStep(evidence); _testContext.AddResultFile(evidence); } } From a1b7bbe41ea9c5d86661175458263ea415bd9449 Mon Sep 17 00:00:00 2001 From: mg-diego Date: Fri, 6 Oct 2023 18:21:25 +0200 Subject: [PATCH 04/17] Solve PR comments --- src/Engines/TestWare.Engines.MongoDB/Factory/ClientFactory.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Engines/TestWare.Engines.MongoDB/Factory/ClientFactory.cs b/src/Engines/TestWare.Engines.MongoDB/Factory/ClientFactory.cs index 4cad0439..b542ec9f 100644 --- a/src/Engines/TestWare.Engines.MongoDB/Factory/ClientFactory.cs +++ b/src/Engines/TestWare.Engines.MongoDB/Factory/ClientFactory.cs @@ -6,6 +6,7 @@ internal class ClientFactory { public static IMongoDbClient Create(Capabilities capabilities) { + if (capabilities == null || capabilities.ConnectionString == null) throw new ArgumentNullException(nameof(capabilities)); return new MongoDbClient(capabilities.ConnectionString); } } From b78c0be1477b388b18e82e2a1c6c484e0bb4fd03 Mon Sep 17 00:00:00 2001 From: mg-diego Date: Fri, 6 Oct 2023 20:05:27 +0200 Subject: [PATCH 05/17] Fix Sonnar_scanner.yml workflow --- .github/workflows/Sonar_Scanner.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/Sonar_Scanner.yml b/.github/workflows/Sonar_Scanner.yml index c6e4e91d..8a4ab4f8 100644 --- a/.github/workflows/Sonar_Scanner.yml +++ b/.github/workflows/Sonar_Scanner.yml @@ -1,6 +1,9 @@ name: SonarQube Scanner on: - pull_request_target: + push: + branches: + - main + pull_request: types: [opened, synchronize, reopened, labeled] workflow_call: secrets: From 03aab5fcddf77d9dd08ad0dadbe168703d18fee9 Mon Sep 17 00:00:00 2001 From: mg-diego Date: Fri, 6 Oct 2023 21:45:48 +0200 Subject: [PATCH 06/17] PoC: AllureReport --- TestWare.sln | 7 ++++ samples/TestWare.Samples.Selenium.Web/Hook.cs | 21 ++++++---- .../TestWare.Samples.Selenium.Web.csproj | 1 + .../specflow.json | 5 +++ .../TestWare.AllureReport/AllureReport.cs | 29 +++++++++++++ .../TestWare.AllureReport.csproj | 17 ++++++++ .../TestWare.AllureReport/allureConfig.json | 41 +++++++++++++++++++ 7 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 samples/TestWare.Samples.Selenium.Web/specflow.json create mode 100644 src/Core/TestWare.AllureReport/AllureReport.cs create mode 100644 src/Core/TestWare.AllureReport/TestWare.AllureReport.csproj create mode 100644 src/Core/TestWare.AllureReport/allureConfig.json diff --git a/TestWare.sln b/TestWare.sln index 3c7ff8cc..6877c087 100644 --- a/TestWare.sln +++ b/TestWare.sln @@ -38,6 +38,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestWare.ExtentReport", "sr EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Reporting", "Reporting", "{DCCEF363-0EBE-46EA-B02B-CD59010626F6}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestWare.AllureReport", "src\Core\TestWare.AllureReport\TestWare.AllureReport.csproj", "{91F2B723-A68B-4711-969B-89897B3C6161}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -84,6 +86,10 @@ Global {94025C6B-DF0D-4AC4-BBC5-A94A9FA3AB0A}.Debug|Any CPU.Build.0 = Debug|Any CPU {94025C6B-DF0D-4AC4-BBC5-A94A9FA3AB0A}.Release|Any CPU.ActiveCfg = Release|Any CPU {94025C6B-DF0D-4AC4-BBC5-A94A9FA3AB0A}.Release|Any CPU.Build.0 = Release|Any CPU + {91F2B723-A68B-4711-969B-89897B3C6161}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91F2B723-A68B-4711-969B-89897B3C6161}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91F2B723-A68B-4711-969B-89897B3C6161}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91F2B723-A68B-4711-969B-89897B3C6161}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -102,6 +108,7 @@ Global {71120454-DD7A-484C-93F2-699B4C363297} = {58B1446D-98A3-46A2-A668-305F0170B39F} {94025C6B-DF0D-4AC4-BBC5-A94A9FA3AB0A} = {DCCEF363-0EBE-46EA-B02B-CD59010626F6} {DCCEF363-0EBE-46EA-B02B-CD59010626F6} = {4678C707-68DB-4E06-9184-A07FB398832C} + {91F2B723-A68B-4711-969B-89897B3C6161} = {DCCEF363-0EBE-46EA-B02B-CD59010626F6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4F88CB24-23C8-4E0E-8B83-29023C1642B8} diff --git a/samples/TestWare.Samples.Selenium.Web/Hook.cs b/samples/TestWare.Samples.Selenium.Web/Hook.cs index a325de53..7bb84a65 100644 --- a/samples/TestWare.Samples.Selenium.Web/Hook.cs +++ b/samples/TestWare.Samples.Selenium.Web/Hook.cs @@ -1,5 +1,6 @@ using System.Globalization; using TestWare.Reporting.ExtentReport; +using TestWare.Reporting.AllureReport; namespace TestWare.Samples.Selenium.Web; @@ -9,7 +10,8 @@ public sealed class Hook private readonly TestContext _testContext; private int _stepCounter; private static readonly LifeCycle _lifeCycle = new(); - private static ExtentReport _testReport; + private static ExtentReport _extentReport; + private static AllureReport _allureReport; public Hook(TestContext testContext) { @@ -23,7 +25,7 @@ public static void BeforeFeature(FeatureContext featureContext) var tags = featureContext.FeatureInfo.Tags; _lifeCycle.BeginTestSuite(name); - _testReport.CreateFeature(name, tags); + _extentReport.CreateFeature(name, tags); } [AfterFeature] @@ -41,7 +43,7 @@ public void BeforeScenario(FeatureContext featureContext, ScenarioContext scenar var description = scenarioContext.ScenarioInfo.Description ?? ""; var scenarioTags = scenarioContext.ScenarioInfo.Tags; - _testReport.CreateTestCase(name, description, scenarioTags); + _extentReport.CreateTestCase(name, description, scenarioTags); _testContext.WriteLine("----------------------------------------- \r\n"); _testContext.WriteLine($"Feature: {featureContext.FeatureInfo.Title}"); @@ -55,7 +57,7 @@ public void BeforeScenario(FeatureContext featureContext, ScenarioContext scenar [AfterScenario] public void AfterScenario() { - _testReport.SetTestcaseOutcome(_testContext.CurrentTestOutcome); + _extentReport.SetTestcaseOutcome(_testContext.CurrentTestOutcome); _lifeCycle.EndTestCase(); } @@ -63,14 +65,16 @@ public void AfterScenario() public static void BeforeTestRun() { _lifeCycle.BeginTestExecution(); - _testReport = new ExtentReport(_lifeCycle.GetCurrentResultsDirectory()); + _extentReport = new ExtentReport(_lifeCycle.GetCurrentResultsDirectory()); + _allureReport = new AllureReport(); + _allureReport.CleanResultsFolder(); } [AfterTestRun] public static void AfterTestRun() { _lifeCycle.EndTestExecution(); - _testReport.CreateTestReportFile(); + _extentReport.CreateTestReportFile(); } [BeforeStep] @@ -78,7 +82,7 @@ public void BeforeStep(ScenarioContext scenarioContext) { var name = scenarioContext.CurrentScenarioBlock.ToString(); var description = scenarioContext.StepContext.StepInfo.Text; - _testReport.CreateStep(name, description); + _extentReport.CreateStep(name, description); var stepId = $"{_stepCounter:00} {description}"; _stepCounter++; @@ -93,7 +97,8 @@ public void AfterStep(ScenarioContext scenarioContext) foreach (var evidence in evidencesPath) { - _testReport.AddScreenshotToStep(evidence); + _extentReport.AddScreenshotToStep(evidence); + _allureReport.AddAttachment(evidence, Path.GetFileNameWithoutExtension(evidence)); _testContext.AddResultFile(evidence); } } diff --git a/samples/TestWare.Samples.Selenium.Web/TestWare.Samples.Selenium.Web.csproj b/samples/TestWare.Samples.Selenium.Web/TestWare.Samples.Selenium.Web.csproj index 07ae10b2..2dd10e69 100644 --- a/samples/TestWare.Samples.Selenium.Web/TestWare.Samples.Selenium.Web.csproj +++ b/samples/TestWare.Samples.Selenium.Web/TestWare.Samples.Selenium.Web.csproj @@ -29,6 +29,7 @@ + diff --git a/samples/TestWare.Samples.Selenium.Web/specflow.json b/samples/TestWare.Samples.Selenium.Web/specflow.json new file mode 100644 index 00000000..e6e9e068 --- /dev/null +++ b/samples/TestWare.Samples.Selenium.Web/specflow.json @@ -0,0 +1,5 @@ +{ + "stepAssemblies": [ + { "assembly": "Allure.SpecFlowPlugin" } + ] +} diff --git a/src/Core/TestWare.AllureReport/AllureReport.cs b/src/Core/TestWare.AllureReport/AllureReport.cs new file mode 100644 index 00000000..0577a3e9 --- /dev/null +++ b/src/Core/TestWare.AllureReport/AllureReport.cs @@ -0,0 +1,29 @@ +using Allure.Commons; +using Allure.Commons.Configuration; + +namespace TestWare.Reporting.AllureReport; + +public class AllureReport : AllureConfiguration +{ + private AllureConfiguration _allureConfiguration; + + public AllureReport(string title, HashSet links) + { + _allureConfiguration = new AllureConfiguration(title, null, links); + } + + public void AddAttachment(string path, string attachmentTitle) + { + AllureLifecycle.Instance.AddAttachment(path, attachmentTitle); + } + + public void CleanResultsFolder() + { + AllureLifecycle.Instance.CleanupResultDirectory(); + } + + public void SetIssueTrackerUrl(string issueTrackerBaseUrl) + { + + } +} diff --git a/src/Core/TestWare.AllureReport/TestWare.AllureReport.csproj b/src/Core/TestWare.AllureReport/TestWare.AllureReport.csproj new file mode 100644 index 00000000..16069aa6 --- /dev/null +++ b/src/Core/TestWare.AllureReport/TestWare.AllureReport.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + diff --git a/src/Core/TestWare.AllureReport/allureConfig.json b/src/Core/TestWare.AllureReport/allureConfig.json new file mode 100644 index 00000000..43704b8b --- /dev/null +++ b/src/Core/TestWare.AllureReport/allureConfig.json @@ -0,0 +1,41 @@ +{ + "allure": { + "directory": "allure-results", + "links": [ + "{link}", + "{issue}", + "{tms}" + ] + }, + "specflow": { + "stepArguments": { + "convertToParameters": "true", + "paramNameRegex": "", + "paramValueRegex": "" + }, + "grouping": { + "suites": { + "parentSuite": "^parentSuite:?(.+)", + "suite": "^suite:?(.+)", + "subSuite": "^subSuite:?(.+)" + }, + "behaviors": { + "epic": "^epic:?(.+)", + "story": "^story:?(.+)" + }, + "packages": { + "package": "^package:?(.+)", + "testClass": "^class:?(.+)", + "testMethod": "^method:?(.+)" + } + }, + "labels": { + "owner": "^owner:?(.+)", + "severity": "^(normal|blocker|critical|minor|trivial)" + }, + "links": { + "issue": "^issue:(\\d+)", + "tms": "^tms:(\\d+)" + } + } +} From 682743cd27d122dfd34b30bb4b0b43a803869ff3 Mon Sep 17 00:00:00 2001 From: mg-diego Date: Sat, 7 Oct 2023 13:21:58 +0200 Subject: [PATCH 07/17] Add workflow --- .github/workflows/Allure_Report.yml | 49 +++++ .github/workflows/Run_web_tests.yml | 179 ++++++++++-------- .../Features/SwagLabs/Login.feature | 4 + samples/TestWare.Samples.Selenium.Web/Hook.cs | 7 +- .../TestConfiguration.Web.json | 21 ++ .../TestWare.Samples.Selenium.Web.csproj | 3 + .../TestWare.AllureReport/AllureReport.cs | 58 +++++- .../Configuration/Capabilities.cs | 24 +++ .../TestWare.AllureReport.csproj | 6 + 9 files changed, 257 insertions(+), 94 deletions(-) create mode 100644 .github/workflows/Allure_Report.yml create mode 100644 src/Core/TestWare.AllureReport/Configuration/Capabilities.cs diff --git a/.github/workflows/Allure_Report.yml b/.github/workflows/Allure_Report.yml new file mode 100644 index 00000000..044edea6 --- /dev/null +++ b/.github/workflows/Allure_Report.yml @@ -0,0 +1,49 @@ +name: allure-report +on: + workflow_call: + inputs: + artifact_name: + required: true + type: string + workflow: + required: true + type: string + + +jobs: + allure: + name: Generate Allure Report + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Get Allure history + uses: actions/checkout@v2 + if: always() + continue-on-error: true + with: + ref: gh-pages + path: gh-pages + + - uses: LexisNexis-Public-GHA/sbs-action-download-artifact@v2.13.1 + with: + workflow: | + ${{ inputs.workflow }} + name: | + ${{ inputs.artifact_name }} + + - name: Allure Report action from marketplace + uses: simple-elf/allure-report-action@master + if: always() + with: + allure_results: allure-results + allure_history: allure-history + keep_reports: 20 + + - name: Deploy report to Github Pages + if: always() + uses: peaceiris/actions-gh-pages@v2 + env: + PERSONAL_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PUBLISH_BRANCH: gh-pages + PUBLISH_DIR: allure-history \ No newline at end of file diff --git a/.github/workflows/Run_web_tests.yml b/.github/workflows/Run_web_tests.yml index 76e4565d..4876ad1b 100644 --- a/.github/workflows/Run_web_tests.yml +++ b/.github/workflows/Run_web_tests.yml @@ -1,84 +1,95 @@ -name: Run-web-tests - -on: - workflow_call: - inputs: - driver_type: - required: true - type: string - test_results_path: - required: true - type: string - environment: - required: true - type: string -jobs: - web-tests: - strategy: - matrix: - os: ${{fromJson(inputs.environment)}} - browser: ${{fromJson(inputs.driver_type)}} - fail-fast: false - - name: Run WEB (${{ matrix.browser }}) tests - ${{ matrix.os }} - runs-on: ${{ matrix.os }} - - steps: - - name: Setup .NET - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 6.0.x - - uses: LexisNexis-Public-GHA/sbs-action-download-artifact@v2.13.1 - with: - workflow: CI.yml - name: testing-artifact-selenium-web - - name: Run git init - run: git init - - name: Get Driver path by browser - run: | - switch ( "${{ matrix.browser }}".ToLower() ) - { - "chrome" { $driverPathRaw = "$env:CHROMEWEBDRIVER" } - "firefox" { $driverPathRaw = "$env:GeckoWebDriver" } - "edge" { $driverPathRaw = "$env:EdgeWebDriver" } - "internetexplorer" { $driverPathRaw = "$env:IEWebDriver" } - } - echo "driverPathRaw=$driverPathRaw" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append - shell: pwsh - - name: config replacement - uses: microsoft/variable-substitution@v1 - with: - files: '.\TestConfiguration.Web.json' - env: - Configurations.0.Capabilities.0.Path: ${{ env.driverPathRaw }} - Configurations.0.Capabilities.0.Driver: ${{ matrix.browser }} - Configurations.1.Capabilities.0.Driver: ${{ matrix.browser }} - Configurations.1.Capabilities.0.Path: ${{ env.driverPathRaw }} - Configurations.1.Capabilities.1.Driver: ${{ matrix.browser }} - Configurations.1.Capabilities.1.Path: ${{ env.driverPathRaw }} - Configurations.1.Capabilities.2.Driver: ${{ matrix.browser }} - Configurations.1.Capabilities.2.Path: ${{ env.driverPathRaw }} - TestResultPath: ${{ inputs.test_results_path }} - - name: Read configuration - id: config_file - uses: juliangruber/read-file-action@v1 - with: - path: '.\TestConfiguration.Web.json' - - name: Echo configuration.json - run: echo "${{ steps.config_file.outputs.content }}" - - name: Run tests - run: dotnet test TestWare.Samples.Selenium.Web.dll --logger "trx;LogFileName=results.trx" --results-directory "${{ inputs.test_results_path }}" - - name: Archive WEB (${{ matrix.browser }}) screenshots - if: always() - uses: actions/upload-artifact@v2 - with: - name: web-${{ matrix.browser }}-screenshots - path: | - ${{ inputs.test_results_path }} - - name: Test Report - uses: dorny/test-reporter@v1 - if: success() || failure() - with: - name: Report - WEB (${{ matrix.browser }} - ${{ matrix.os }}) - path: ${{ inputs.test_results_path }}/results.trx - reporter: dotnet-trx +name: Run-web-tests + +on: + workflow_call: + inputs: + driver_type: + required: true + type: string + test_results_path: + required: true + type: string + environment: + required: true + type: string +jobs: + web-tests: + strategy: + matrix: + os: ${{fromJson(inputs.environment)}} + browser: ${{fromJson(inputs.driver_type)}} + fail-fast: false + + name: Run WEB (${{ matrix.browser }}) tests - ${{ matrix.os }} + runs-on: ${{ matrix.os }} + + steps: + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 6.0.x + - uses: LexisNexis-Public-GHA/sbs-action-download-artifact@v2.13.1 + with: + workflow: CI.yml + name: testing-artifact-selenium-web + - name: Run git init + run: git init + - name: Get Driver path by browser + run: | + switch ( "${{ matrix.browser }}".ToLower() ) + { + "chrome" { $driverPathRaw = "$env:CHROMEWEBDRIVER" } + "firefox" { $driverPathRaw = "$env:GeckoWebDriver" } + "edge" { $driverPathRaw = "$env:EdgeWebDriver" } + "internetexplorer" { $driverPathRaw = "$env:IEWebDriver" } + } + echo "driverPathRaw=$driverPathRaw" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append + shell: pwsh + - name: config replacement + uses: microsoft/variable-substitution@v1 + with: + files: '.\TestConfiguration.Web.json' + env: + Configurations.0.Capabilities.0.Path: ${{ env.driverPathRaw }} + Configurations.0.Capabilities.0.Driver: ${{ matrix.browser }} + Configurations.1.Capabilities.0.Driver: ${{ matrix.browser }} + Configurations.1.Capabilities.0.Path: ${{ env.driverPathRaw }} + Configurations.1.Capabilities.1.Driver: ${{ matrix.browser }} + Configurations.1.Capabilities.1.Path: ${{ env.driverPathRaw }} + Configurations.1.Capabilities.2.Driver: ${{ matrix.browser }} + Configurations.1.Capabilities.2.Path: ${{ env.driverPathRaw }} + TestResultPath: ${{ inputs.test_results_path }} + - name: Read configuration + id: config_file + uses: juliangruber/read-file-action@v1 + with: + path: '.\TestConfiguration.Web.json' + - name: Echo configuration.json + run: echo "${{ steps.config_file.outputs.content }}" + - name: Run tests + run: dotnet test TestWare.Samples.Selenium.Web.dll --logger "trx;LogFileName=results.trx" --results-directory "${{ inputs.test_results_path }}" + - name: Archive WEB (${{ matrix.browser }}) screenshots + if: always() + uses: actions/upload-artifact@v2 + with: + name: web-${{ matrix.browser }}-screenshots + path: | + ${{ inputs.test_results_path }} + - name: Archive Testing artifacts - Allure + uses: actions/upload-artifact@v2 + with: + name: allure-results-web + path: '.\allure-results' + - name: Test Report + uses: dorny/test-reporter@v1 + if: success() || failure() + with: + name: Report - WEB (${{ matrix.browser }} - ${{ matrix.os }}) + path: ${{ inputs.test_results_path }}/results.trx + reporter: dotnet-trx + + allure-results: + uses: ./.github/workflows/Allure_Report.yml + with: + artifact_name: 'allure-results-web' + workflow: 'Run_web_tests.yml' diff --git a/samples/TestWare.Samples.Selenium.Web/Features/SwagLabs/Login.feature b/samples/TestWare.Samples.Selenium.Web/Features/SwagLabs/Login.feature index 70cf142d..d4bf237e 100644 --- a/samples/TestWare.Samples.Selenium.Web/Features/SwagLabs/Login.feature +++ b/samples/TestWare.Samples.Selenium.Web/Features/SwagLabs/Login.feature @@ -1,6 +1,7 @@ @WebDriver Feature: Login +@critical Scenario Outline: Login Given the user enters username '' And the user enters password '' @@ -12,6 +13,9 @@ Scenario Outline: Login | standard | standard_user | secret_sauce | | problem | problem_user | secret_sauce | +@blocker +@tms:5 +@issue:3 Scenario: Logout Given user 'standard_user' is logged with 'secret_sauce' into SwagLabs When the user clicks Logout button diff --git a/samples/TestWare.Samples.Selenium.Web/Hook.cs b/samples/TestWare.Samples.Selenium.Web/Hook.cs index 7bb84a65..2ab590a1 100644 --- a/samples/TestWare.Samples.Selenium.Web/Hook.cs +++ b/samples/TestWare.Samples.Selenium.Web/Hook.cs @@ -65,9 +65,12 @@ public void AfterScenario() public static void BeforeTestRun() { _lifeCycle.BeginTestExecution(); - _extentReport = new ExtentReport(_lifeCycle.GetCurrentResultsDirectory()); - _allureReport = new AllureReport(); + _extentReport = new ExtentReport(_lifeCycle.GetCurrentResultsDirectory()); + + var allureConfiguration = _lifeCycle.TestConfiguration.Configurations.First(x=>x.Tag == "AllureConfiguration"); + _allureReport = new AllureReport(allureConfiguration.Capabilities.FirstOrDefault()); _allureReport.CleanResultsFolder(); + _allureReport.GenerateAllureEnvironmentFile(); } [AfterTestRun] diff --git a/samples/TestWare.Samples.Selenium.Web/TestConfiguration.Web.json b/samples/TestWare.Samples.Selenium.Web/TestConfiguration.Web.json index a6053a2b..26be19d3 100644 --- a/samples/TestWare.Samples.Selenium.Web/TestConfiguration.Web.json +++ b/samples/TestWare.Samples.Selenium.Web/TestConfiguration.Web.json @@ -83,6 +83,27 @@ ] } ] + }, + { + "Tag": "AllureConfiguration", + "Capabilities": [ + { + "IssueTrackerBaseUrl": "https://www.myissuetracker.com/", + "IssueTagRegex": "^issue:(\\d+)", + "TestManagementSystemBaseUrl": "https://www.mytms.com/", + "TestManagementSystemTagRegex": "^tms:(\\d+)", + "EnvironmentValues": [ + { + "key": "System", + "value": "Windows" + }, + { + "key": "WebDriver", + "value": "Chrome" + } + ] + } + ] } ], "TestResultPath": "C:\\workspace\\ERNI\\results\\" diff --git a/samples/TestWare.Samples.Selenium.Web/TestWare.Samples.Selenium.Web.csproj b/samples/TestWare.Samples.Selenium.Web/TestWare.Samples.Selenium.Web.csproj index 2dd10e69..de40c02e 100644 --- a/samples/TestWare.Samples.Selenium.Web/TestWare.Samples.Selenium.Web.csproj +++ b/samples/TestWare.Samples.Selenium.Web/TestWare.Samples.Selenium.Web.csproj @@ -41,6 +41,9 @@ + + Always + Always diff --git a/src/Core/TestWare.AllureReport/AllureReport.cs b/src/Core/TestWare.AllureReport/AllureReport.cs index 0577a3e9..0a091486 100644 --- a/src/Core/TestWare.AllureReport/AllureReport.cs +++ b/src/Core/TestWare.AllureReport/AllureReport.cs @@ -1,15 +1,27 @@ using Allure.Commons; -using Allure.Commons.Configuration; +using Newtonsoft.Json; +using System.Text; +using System.Text.Json.Nodes; +using System.Text.RegularExpressions; namespace TestWare.Reporting.AllureReport; -public class AllureReport : AllureConfiguration +public class AllureReport { - private AllureConfiguration _allureConfiguration; + private const string AllureConfigFile = "allureConfig.json"; + private const string AllureEnvironmentFile = "environment.properties"; + private const string AllureResultsFolder = "allure-results"; - public AllureReport(string title, HashSet links) + private readonly Capabilities AllureCapabilities; + + public AllureReport(JsonObject capabilities) { - _allureConfiguration = new AllureConfiguration(title, null, links); + if (capabilities == null) throw new ArgumentNullException(nameof(capabilities)); + AllureCapabilities = JsonConvert.DeserializeObject(capabilities.ToString()); + + if (AllureCapabilities == null) throw new ArgumentNullException(nameof(AllureCapabilities)); + SetIssueTrackerBaseUrl(AllureCapabilities.IssueTrackerBaseUrl); + SetTestManagementSystemBaseUrl(AllureCapabilities.TestManagementSystemBaseUrl); } public void AddAttachment(string path, string attachmentTitle) @@ -22,8 +34,38 @@ public void CleanResultsFolder() AllureLifecycle.Instance.CleanupResultDirectory(); } - public void SetIssueTrackerUrl(string issueTrackerBaseUrl) - { - + public void GenerateAllureEnvironmentFile() + { + using var sw = new StreamWriter(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AllureResultsFolder, AllureEnvironmentFile), true); + foreach (var keyValuePair in AllureCapabilities.EnvironmentValues) + { + sw.WriteLine("{0}={1}", keyValuePair.Key, keyValuePair.Value); + } + } + + private void SetIssueTrackerBaseUrl(string issueTrackerBaseUrl) + { + string text = ReadAllureConfigFile(); + text = Regex.Replace(text, @".*{issue}.*", '"' + issueTrackerBaseUrl + "{issue}"); + WriteAllureConfigFile(text); + } + + private void SetTestManagementSystemBaseUrl(string testManagementSystemBaseUrl) + { + string text = ReadAllureConfigFile(); + text = Regex.Replace(text, @".*{tms}.*", '"' + testManagementSystemBaseUrl + "{tms}"); + WriteAllureConfigFile(text); + } + + private string ReadAllureConfigFile() + { + var allureConfigPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AllureConfigFile); + return File.ReadAllText(allureConfigPath, Encoding.UTF8); + } + + private void WriteAllureConfigFile(string text) + { + var allureConfigPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AllureConfigFile); + File.WriteAllText(allureConfigPath, text); } } diff --git a/src/Core/TestWare.AllureReport/Configuration/Capabilities.cs b/src/Core/TestWare.AllureReport/Configuration/Capabilities.cs new file mode 100644 index 00000000..5809d1e4 --- /dev/null +++ b/src/Core/TestWare.AllureReport/Configuration/Capabilities.cs @@ -0,0 +1,24 @@ +using Newtonsoft.Json; + +namespace TestWare.Reporting.AllureReport; + +internal class Capabilities +{ + public string? IssueTrackerBaseUrl { get; set; } + + public string? IssueTagRegex { get; set; } + + public string? TestManagementSystemBaseUrl { get; set; } + + public string? TestManagementSystemTagRegex { get; set; } + + public IEnumerable EnvironmentValues { get; set; } = Enumerable.Empty(); +} + +public partial class EnvironmentValue +{ + public string? Key { get; set; } + + public string? Value { get; set; } +} + diff --git a/src/Core/TestWare.AllureReport/TestWare.AllureReport.csproj b/src/Core/TestWare.AllureReport/TestWare.AllureReport.csproj index 16069aa6..0b5667ce 100644 --- a/src/Core/TestWare.AllureReport/TestWare.AllureReport.csproj +++ b/src/Core/TestWare.AllureReport/TestWare.AllureReport.csproj @@ -14,4 +14,10 @@ + + + Always + + + From f049d7f0929614ca9750ff8dec88d99ebb3be558 Mon Sep 17 00:00:00 2001 From: mg-diego Date: Sat, 7 Oct 2023 13:36:12 +0200 Subject: [PATCH 08/17] Fix sonnar comments --- src/Core/TestWare.AllureReport/AllureReport.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Core/TestWare.AllureReport/AllureReport.cs b/src/Core/TestWare.AllureReport/AllureReport.cs index 0a091486..6828ef3b 100644 --- a/src/Core/TestWare.AllureReport/AllureReport.cs +++ b/src/Core/TestWare.AllureReport/AllureReport.cs @@ -16,12 +16,11 @@ public class AllureReport public AllureReport(JsonObject capabilities) { - if (capabilities == null) throw new ArgumentNullException(nameof(capabilities)); - AllureCapabilities = JsonConvert.DeserializeObject(capabilities.ToString()); - if (AllureCapabilities == null) throw new ArgumentNullException(nameof(AllureCapabilities)); - SetIssueTrackerBaseUrl(AllureCapabilities.IssueTrackerBaseUrl); - SetTestManagementSystemBaseUrl(AllureCapabilities.TestManagementSystemBaseUrl); + AllureCapabilities = JsonConvert.DeserializeObject(capabilities.ToString()) ?? throw new ArgumentNullException(nameof(capabilities)); + + SetIssueTrackerBaseUrl(AllureCapabilities.IssueTrackerBaseUrl ?? throw new ArgumentNullException(nameof(AllureCapabilities.IssueTrackerBaseUrl))); + SetTestManagementSystemBaseUrl(AllureCapabilities.TestManagementSystemBaseUrl ?? throw new ArgumentNullException(nameof(AllureCapabilities.TestManagementSystemBaseUrl))); } public void AddAttachment(string path, string attachmentTitle) From 1f09d1efa3212492e7143e84d683c895f8f4965e Mon Sep 17 00:00:00 2001 From: mg-diego Date: Sat, 7 Oct 2023 14:54:53 +0200 Subject: [PATCH 09/17] Fix YML file indentation --- .github/workflows/Run_web_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Run_web_tests.yml b/.github/workflows/Run_web_tests.yml index 4876ad1b..000e8c6b 100644 --- a/.github/workflows/Run_web_tests.yml +++ b/.github/workflows/Run_web_tests.yml @@ -76,8 +76,8 @@ jobs: path: | ${{ inputs.test_results_path }} - name: Archive Testing artifacts - Allure - uses: actions/upload-artifact@v2 - with: + uses: actions/upload-artifact@v2 + with: name: allure-results-web path: '.\allure-results' - name: Test Report From 54bc5a8713999bd64fa6bf75134ea4abe2812f22 Mon Sep 17 00:00:00 2001 From: mg-diego Date: Sat, 7 Oct 2023 14:58:16 +0200 Subject: [PATCH 10/17] Fix Allure Report YML indentation --- .github/workflows/Allure_Report.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Allure_Report.yml b/.github/workflows/Allure_Report.yml index 044edea6..5f8dcae5 100644 --- a/.github/workflows/Allure_Report.yml +++ b/.github/workflows/Allure_Report.yml @@ -25,8 +25,8 @@ jobs: ref: gh-pages path: gh-pages - - uses: LexisNexis-Public-GHA/sbs-action-download-artifact@v2.13.1 - with: + - uses: LexisNexis-Public-GHA/sbs-action-download-artifact@v2.13.1 + with: workflow: | ${{ inputs.workflow }} name: | From 6b6a7a455b0350cab0be178bc247f0c4f8562aba Mon Sep 17 00:00:00 2001 From: mg-diego Date: Sat, 7 Oct 2023 15:03:36 +0200 Subject: [PATCH 11/17] Fix indentation --- .github/workflows/Allure_Report.yml | 64 ++++++++++++++--------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/.github/workflows/Allure_Report.yml b/.github/workflows/Allure_Report.yml index 5f8dcae5..4a62f4e4 100644 --- a/.github/workflows/Allure_Report.yml +++ b/.github/workflows/Allure_Report.yml @@ -12,38 +12,38 @@ on: jobs: allure: - name: Generate Allure Report - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 + name: Generate Allure Report + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 - - name: Get Allure history - uses: actions/checkout@v2 - if: always() - continue-on-error: true - with: - ref: gh-pages - path: gh-pages - - - uses: LexisNexis-Public-GHA/sbs-action-download-artifact@v2.13.1 - with: - workflow: | - ${{ inputs.workflow }} - name: | - ${{ inputs.artifact_name }} + - name: Get Allure history + uses: actions/checkout@v2 + if: always() + continue-on-error: true + with: + ref: gh-pages + path: gh-pages + + - uses: LexisNexis-Public-GHA/sbs-action-download-artifact@v2.13.1 + with: + workflow: | + ${{ inputs.workflow }} + name: | + ${{ inputs.artifact_name }} - - name: Allure Report action from marketplace - uses: simple-elf/allure-report-action@master - if: always() - with: - allure_results: allure-results - allure_history: allure-history - keep_reports: 20 + - name: Allure Report action from marketplace + uses: simple-elf/allure-report-action@master + if: always() + with: + allure_results: allure-results + allure_history: allure-history + keep_reports: 20 - - name: Deploy report to Github Pages - if: always() - uses: peaceiris/actions-gh-pages@v2 - env: - PERSONAL_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PUBLISH_BRANCH: gh-pages - PUBLISH_DIR: allure-history \ No newline at end of file + - name: Deploy report to Github Pages + if: always() + uses: peaceiris/actions-gh-pages@v2 + env: + PERSONAL_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PUBLISH_BRANCH: gh-pages + PUBLISH_DIR: allure-history \ No newline at end of file From c93fdc5cc1f8c9440ee6d1f7646335e6d8dc759d Mon Sep 17 00:00:00 2001 From: mg-diego Date: Sat, 7 Oct 2023 15:33:41 +0200 Subject: [PATCH 12/17] Fix API tests --- .github/workflows/Run_web_tests.yml | 2 ++ samples/TestWare.Samples.API/Features/AgeCalculations.feature | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/Run_web_tests.yml b/.github/workflows/Run_web_tests.yml index 000e8c6b..b9c80d2e 100644 --- a/.github/workflows/Run_web_tests.yml +++ b/.github/workflows/Run_web_tests.yml @@ -65,6 +65,7 @@ jobs: with: path: '.\TestConfiguration.Web.json' - name: Echo configuration.json + continue-on-error: true run: echo "${{ steps.config_file.outputs.content }}" - name: Run tests run: dotnet test TestWare.Samples.Selenium.Web.dll --logger "trx;LogFileName=results.trx" --results-directory "${{ inputs.test_results_path }}" @@ -89,6 +90,7 @@ jobs: reporter: dotnet-trx allure-results: + needs: web-tests uses: ./.github/workflows/Allure_Report.yml with: artifact_name: 'allure-results-web' diff --git a/samples/TestWare.Samples.API/Features/AgeCalculations.feature b/samples/TestWare.Samples.API/Features/AgeCalculations.feature index 9697ba1f..26cf1bda 100644 --- a/samples/TestWare.Samples.API/Features/AgeCalculations.feature +++ b/samples/TestWare.Samples.API/Features/AgeCalculations.feature @@ -8,5 +8,5 @@ A short summary of the feature Scenario: Scenario that combines two different apis Given A calculated age for name 'Name' - When the formula '22*2' is simplified on 'api1' + When the formula '22+23' is simplified on 'api1' Then Age and expresion should be the same From 115d834b9e7843c1e27e750504cf1401e5262a9d Mon Sep 17 00:00:00 2001 From: mg-diego Date: Sat, 7 Oct 2023 15:46:45 +0200 Subject: [PATCH 13/17] Force job execution --- .github/workflows/Run_web_tests.yml | 2 ++ .../TestWare.Samples.Selenium.Web/TestConfiguration.Web.json | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Run_web_tests.yml b/.github/workflows/Run_web_tests.yml index b9c80d2e..67b95f1d 100644 --- a/.github/workflows/Run_web_tests.yml +++ b/.github/workflows/Run_web_tests.yml @@ -77,6 +77,7 @@ jobs: path: | ${{ inputs.test_results_path }} - name: Archive Testing artifacts - Allure + if: always() uses: actions/upload-artifact@v2 with: name: allure-results-web @@ -91,6 +92,7 @@ jobs: allure-results: needs: web-tests + if: always() uses: ./.github/workflows/Allure_Report.yml with: artifact_name: 'allure-results-web' diff --git a/samples/TestWare.Samples.Selenium.Web/TestConfiguration.Web.json b/samples/TestWare.Samples.Selenium.Web/TestConfiguration.Web.json index 26be19d3..1e704698 100644 --- a/samples/TestWare.Samples.Selenium.Web/TestConfiguration.Web.json +++ b/samples/TestWare.Samples.Selenium.Web/TestConfiguration.Web.json @@ -89,9 +89,7 @@ "Capabilities": [ { "IssueTrackerBaseUrl": "https://www.myissuetracker.com/", - "IssueTagRegex": "^issue:(\\d+)", "TestManagementSystemBaseUrl": "https://www.mytms.com/", - "TestManagementSystemTagRegex": "^tms:(\\d+)", "EnvironmentValues": [ { "key": "System", From d1e747a930be6e56986d0d1eb90fdccfc502dc70 Mon Sep 17 00:00:00 2001 From: mg-diego Date: Sat, 7 Oct 2023 16:15:53 +0200 Subject: [PATCH 14/17] Fixes for YML files --- .github/workflows/Allure_Report.yml | 2 ++ .github/workflows/Run_web_tests.yml | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Allure_Report.yml b/.github/workflows/Allure_Report.yml index 4a62f4e4..76dfa0a6 100644 --- a/.github/workflows/Allure_Report.yml +++ b/.github/workflows/Allure_Report.yml @@ -31,6 +31,8 @@ jobs: ${{ inputs.workflow }} name: | ${{ inputs.artifact_name }} + workflow_conclusion: success + path: allure-results - name: Allure Report action from marketplace uses: simple-elf/allure-report-action@master diff --git a/.github/workflows/Run_web_tests.yml b/.github/workflows/Run_web_tests.yml index 67b95f1d..d6844780 100644 --- a/.github/workflows/Run_web_tests.yml +++ b/.github/workflows/Run_web_tests.yml @@ -58,6 +58,12 @@ jobs: Configurations.1.Capabilities.1.Path: ${{ env.driverPathRaw }} Configurations.1.Capabilities.2.Driver: ${{ matrix.browser }} Configurations.1.Capabilities.2.Path: ${{ env.driverPathRaw }} + Configurations.1.Capabilities.3.Driver: ${{ matrix.browser }} + Configurations.1.Capabilities.3.Path: ${{ env.driverPathRaw }} + Configurations.1.Capabilities.4.Driver: ${{ matrix.browser }} + Configurations.1.Capabilities.4.Path: ${{ env.driverPathRaw }} + Configurations.1.Capabilities.5.Driver: ${{ matrix.browser }} + Configurations.1.Capabilities.5.Path: ${{ env.driverPathRaw }} TestResultPath: ${{ inputs.test_results_path }} - name: Read configuration id: config_file @@ -95,5 +101,5 @@ jobs: if: always() uses: ./.github/workflows/Allure_Report.yml with: - artifact_name: 'allure-results-web' - workflow: 'Run_web_tests.yml' + artifact_name: allure-results-web + workflow: Run_web_tests.yml From 7d21418b3d5cdebefc459a02d0a9cb5f41f448da Mon Sep 17 00:00:00 2001 From: mg-diego Date: Sat, 7 Oct 2023 16:31:36 +0200 Subject: [PATCH 15/17] Adapt allure report trigger --- .github/workflows/Allure_Report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Allure_Report.yml b/.github/workflows/Allure_Report.yml index 76dfa0a6..028abd1d 100644 --- a/.github/workflows/Allure_Report.yml +++ b/.github/workflows/Allure_Report.yml @@ -31,7 +31,7 @@ jobs: ${{ inputs.workflow }} name: | ${{ inputs.artifact_name }} - workflow_conclusion: success + workflow_conclusion: success, failure, completed path: allure-results - name: Allure Report action from marketplace From b038c8022e454dbf2d6f78cc8ac39f15333ec3d0 Mon Sep 17 00:00:00 2001 From: mg-diego Date: Sat, 7 Oct 2023 16:51:52 +0200 Subject: [PATCH 16/17] Fix WEB tests --- .github/workflows/Allure_Report.yml | 7 ++----- .github/workflows/Run_web_tests.yml | 4 ++-- .../Features/Stinto/Chat_multibrowser.feature | 10 +++++----- .../Features/SwagLabs/Login_multibrowser.feature | 4 ++-- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/.github/workflows/Allure_Report.yml b/.github/workflows/Allure_Report.yml index 028abd1d..a64855dd 100644 --- a/.github/workflows/Allure_Report.yml +++ b/.github/workflows/Allure_Report.yml @@ -27,11 +27,8 @@ jobs: - uses: LexisNexis-Public-GHA/sbs-action-download-artifact@v2.13.1 with: - workflow: | - ${{ inputs.workflow }} - name: | - ${{ inputs.artifact_name }} - workflow_conclusion: success, failure, completed + workflow: ${{ inputs.workflow }} + name: ${{ inputs.artifact_name }} path: allure-results - name: Allure Report action from marketplace diff --git a/.github/workflows/Run_web_tests.yml b/.github/workflows/Run_web_tests.yml index d6844780..85fdd08c 100644 --- a/.github/workflows/Run_web_tests.yml +++ b/.github/workflows/Run_web_tests.yml @@ -86,7 +86,7 @@ jobs: if: always() uses: actions/upload-artifact@v2 with: - name: allure-results-web + name: allure-results path: '.\allure-results' - name: Test Report uses: dorny/test-reporter@v1 @@ -101,5 +101,5 @@ jobs: if: always() uses: ./.github/workflows/Allure_Report.yml with: - artifact_name: allure-results-web + artifact_name: allure-results workflow: Run_web_tests.yml diff --git a/samples/TestWare.Samples.Selenium.Web/Features/Stinto/Chat_multibrowser.feature b/samples/TestWare.Samples.Selenium.Web/Features/Stinto/Chat_multibrowser.feature index f56d8a15..87cd643b 100644 --- a/samples/TestWare.Samples.Selenium.Web/Features/Stinto/Chat_multibrowser.feature +++ b/samples/TestWare.Samples.Selenium.Web/Features/Stinto/Chat_multibrowser.feature @@ -4,9 +4,9 @@ Feature: Chat_multibrowser @browser1Chat @browser2Chat Scenario: Chat between two users - Given the 'user1' creates a new chat session on 'browser1' - When the 'user2' joins chat session on 'browser2' - Then the 'has joined.' message from 'user2' appears on 'browser1' - And the 'has joined.' message from 'user1' appears on 'browser2' - When the user sends 'a test' message on 'browser1' + Given the 'user1' creates a new chat session on 'browser1Chat' + When the 'user2' joins chat session on 'browser2Chat' + Then the 'has joined.' message from 'user2' appears on 'browser1Chat' + And the 'has joined.' message from 'user1' appears on 'browser2Chat' + When the user sends 'a test' message on 'browser1Chat' Then the 'a test' message from 'user1' appears on all browsers diff --git a/samples/TestWare.Samples.Selenium.Web/Features/SwagLabs/Login_multibrowser.feature b/samples/TestWare.Samples.Selenium.Web/Features/SwagLabs/Login_multibrowser.feature index 52c4afe3..40349e7b 100644 --- a/samples/TestWare.Samples.Selenium.Web/Features/SwagLabs/Login_multibrowser.feature +++ b/samples/TestWare.Samples.Selenium.Web/Features/SwagLabs/Login_multibrowser.feature @@ -14,5 +14,5 @@ Scenario: Login on multiple browsers and logout browser2 And the user enters password 'secret_sauce' on all And the user clicks submit on all And the user can login on all - When the user clicks Logout button on 'browser2' - Then the user is at Login page on 'browser2' + When the user clicks Logout button on 'browser2Swaglabs' + Then the user is at Login page on 'browser2Swaglabs' From ac06cd141f163967c919590b0a6c916aa6988fde Mon Sep 17 00:00:00 2001 From: Diego Martinez Date: Thu, 23 May 2024 14:23:26 +0200 Subject: [PATCH 17/17] Fix JDK version --- .github/workflows/Sonar_Scanner.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Sonar_Scanner.yml b/.github/workflows/Sonar_Scanner.yml index 8a4ab4f8..188eb1a0 100644 --- a/.github/workflows/Sonar_Scanner.yml +++ b/.github/workflows/Sonar_Scanner.yml @@ -31,10 +31,10 @@ jobs: uses: actions/setup-dotnet@v1 with: dotnet-version: 6.0.x - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v1 with: - java-version: 1.11 + java-version: 17 - uses: actions/checkout@v2 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis