diff --git a/Migrators/ZephyrScaleServerExporter/Client/Client.cs b/Migrators/ZephyrScaleServerExporter/Client/Client.cs index 25bf8a0..9e6c8b8 100644 --- a/Migrators/ZephyrScaleServerExporter/Client/Client.cs +++ b/Migrators/ZephyrScaleServerExporter/Client/Client.cs @@ -179,6 +179,63 @@ public async Task GetArchivedTestCase(string testCaseKey return testCase; } + public async Task GetParametersByTestCaseKey(string testCaseKey) + { + _logger.LogInformation("Getting parameters by test case key {Key}", testCaseKey); + + var response = await _httpClient.GetAsync($"/rest/tests/1.0/testcase/{testCaseKey}?fields=testData,parameters(id,name,defaultValue,index),paramType"); + if (!response.IsSuccessStatusCode) + { + _logger.LogError( + "Failed to get parameters by test case key {Key}. Status code: {StatusCode}. Response: {Response}", + testCaseKey, response.StatusCode, await response.Content.ReadAsStringAsync()); + + throw new Exception($"Failed to get parameters by test case key {testCaseKey}. Status code: {response.StatusCode}"); + } + + var content = await response.Content.ReadAsStringAsync(); + var zephyrParametersData = JsonSerializer.Deserialize(content); + var testData = new List>(); + + if (zephyrParametersData.TestData.Count != 0) + { + foreach (var zephyrIteration in zephyrParametersData.TestData) + { + var dataParameters = new Dictionary(); + + foreach (var parameterName in zephyrIteration.Keys) + { + try + { + var parameter = JsonSerializer.Deserialize(zephyrIteration[parameterName].ToString()); + + dataParameters[parameterName] = parameter; + } + catch (Exception) + { + continue; + } + } + + if (dataParameters.Keys.Count != 0) + { + testData.Add(dataParameters); + } + } + } + + var parametersData = new ParametersData + { + Type = zephyrParametersData.Type, + TestData = testData, + Parameters = zephyrParametersData.Parameters + }; + + _logger.LogDebug("Got parameters: {@Parameters}", parametersData); + + return parametersData; + } + public async Task> GetComponents() { _logger.LogInformation("Getting components by project key {Key}", _projectKey); diff --git a/Migrators/ZephyrScaleServerExporter/Client/IClient.cs b/Migrators/ZephyrScaleServerExporter/Client/IClient.cs index f0bb5c4..1bb09bc 100644 --- a/Migrators/ZephyrScaleServerExporter/Client/IClient.cs +++ b/Migrators/ZephyrScaleServerExporter/Client/IClient.cs @@ -9,6 +9,7 @@ public interface IClient Task> GetTestCases(); Task GetTestCase(string testCaseKey); Task GetArchivedTestCase(string testCaseKey); + Task GetParametersByTestCaseKey(string testCaseKey); Task> GetComponents(); Task GetIssueById(string issueId); Task> GetAttachmentsForTestCase(string testCaseKey); diff --git a/Migrators/ZephyrScaleServerExporter/Models/StepsData.cs b/Migrators/ZephyrScaleServerExporter/Models/StepsData.cs new file mode 100644 index 0000000..febdc4d --- /dev/null +++ b/Migrators/ZephyrScaleServerExporter/Models/StepsData.cs @@ -0,0 +1,9 @@ +using Models; + +namespace ZephyrScaleServerExporter.Models; + +public class StepsData +{ + public List Steps { get; set; } + public List Iterations { get; set; } +} diff --git a/Migrators/ZephyrScaleServerExporter/Models/ZephyrParameterType.cs b/Migrators/ZephyrScaleServerExporter/Models/ZephyrParameterType.cs new file mode 100644 index 0000000..e7d4390 --- /dev/null +++ b/Migrators/ZephyrScaleServerExporter/Models/ZephyrParameterType.cs @@ -0,0 +1,7 @@ +namespace ZephyrScaleServerExporter.Models; + +public class ZephyrParameterType +{ + public const string TEST_DATA = "TEST_DATA"; + public const string PARAMETER = "PARAMETER"; +} diff --git a/Migrators/ZephyrScaleServerExporter/Models/ZephyrParametersData.cs b/Migrators/ZephyrScaleServerExporter/Models/ZephyrParametersData.cs new file mode 100644 index 0000000..f9ed951 --- /dev/null +++ b/Migrators/ZephyrScaleServerExporter/Models/ZephyrParametersData.cs @@ -0,0 +1,63 @@ +using System.Text.Json.Serialization; + +namespace ZephyrScaleServerExporter.Models; + +public class ZephyrParametersData +{ + [JsonPropertyName("paramType")] + public string Type { get; set; } + + [JsonPropertyName("testData")] + public List> TestData { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("id")] + public int Id { get; set; } + + [JsonPropertyName("parameters")] + public List Parameters { get; set; } +} + +public class ParametersData +{ + public string Type { get; set; } + public List> TestData { get; set; } + public List Parameters { get; set; } +} + +public class ZephyrDataParameter +{ + [JsonPropertyName("index")] + public int Index { get; set; } + + [JsonPropertyName("value")] + public string Value { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("dataSetItemId")] + public int DataSetItemId { get; set; } +} + +public class DataParameter +{ + List Parameters; +} + +public class ZephyrParameter +{ + [JsonPropertyName("defaultValue")] + public string Value { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("index")] + public int Index { get; set; } + + [JsonPropertyName("id")] + public int Id { get; set; } +} diff --git a/Migrators/ZephyrScaleServerExporter/Program.cs b/Migrators/ZephyrScaleServerExporter/Program.cs index b35363c..5d2795b 100644 --- a/Migrators/ZephyrScaleServerExporter/Program.cs +++ b/Migrators/ZephyrScaleServerExporter/Program.cs @@ -60,6 +60,7 @@ static IHostBuilder CreateHostBuilder(string[] strings) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); }); } diff --git a/Migrators/ZephyrScaleServerExporter/Services/IParameterService.cs b/Migrators/ZephyrScaleServerExporter/Services/IParameterService.cs new file mode 100644 index 0000000..c11864c --- /dev/null +++ b/Migrators/ZephyrScaleServerExporter/Services/IParameterService.cs @@ -0,0 +1,9 @@ +using Models; + +namespace ZephyrScaleServerExporter.Services; + +public interface IParameterService +{ + Task> ConvertParameters(string testCaseKey); + List MergeIterations(List mainIterations, List subIterations); +} diff --git a/Migrators/ZephyrScaleServerExporter/Services/IStepService.cs b/Migrators/ZephyrScaleServerExporter/Services/IStepService.cs index 5d9c902..5288bf0 100644 --- a/Migrators/ZephyrScaleServerExporter/Services/IStepService.cs +++ b/Migrators/ZephyrScaleServerExporter/Services/IStepService.cs @@ -5,6 +5,5 @@ namespace ZephyrScaleServerExporter.Services; public interface IStepService { - Task> ConvertSteps(Guid testCaseId, ZephyrTestScript testScript); - Task> ConvertSteps(Guid testCaseId, ZephyrArchivedTestScript testScript); + Task ConvertSteps(Guid testCaseId, ZephyrTestScript testScript, List iteranions); } diff --git a/Migrators/ZephyrScaleServerExporter/Services/ParameterService.cs b/Migrators/ZephyrScaleServerExporter/Services/ParameterService.cs new file mode 100644 index 0000000..ce6568f --- /dev/null +++ b/Migrators/ZephyrScaleServerExporter/Services/ParameterService.cs @@ -0,0 +1,113 @@ +using ZephyrScaleServerExporter.Client; +using ZephyrScaleServerExporter.Models; +using Microsoft.Extensions.Logging; +using Models; +using Microsoft.VisualBasic; + +namespace ZephyrScaleServerExporter.Services; + +public class ParameterService : IParameterService +{ + private readonly ILogger _logger; + private readonly IClient _client; + + public ParameterService(ILogger logger, IClient client) + { + _logger = logger; + _client = client; + } + + public async Task> ConvertParameters(string testCaseKey) + { + _logger.LogInformation("Converting parameters"); + + var parametersData = await _client.GetParametersByTestCaseKey(testCaseKey); + + switch (parametersData.Type) + { + case ZephyrParameterType.TEST_DATA: + return ConvertParametersWithTestDataType(parametersData.TestData); + case ZephyrParameterType.PARAMETER: + return ConvertParametersWithParameterType(parametersData.Parameters); + default: + return new List(); + } + } + + public List MergeIterations(List mainIterations, List subIterations) + { + _logger.LogInformation("Merging parameters:\nMain: {@MainParameters}\n Sub: {@SubParameters}", + mainIterations, subIterations); + + foreach (var mainIteration in mainIterations) + { + foreach (var subIteration in subIterations) + { + var nonconflictingIterationParameters = subIteration.Parameters.Where( + subp => mainIteration.Parameters.FirstOrDefault( + mainp => subp.Name == mainp.Name) == null); + + mainIteration.Parameters.AddRange(nonconflictingIterationParameters); + } + } + + _logger.LogInformation("Merged parameters: {@Parameters}", mainIterations); + + return mainIterations; + } + + private List ConvertParametersWithTestDataType(List> ZephyrTestData) + { + var iterations = new List(); + + foreach (var zephyrDataParameters in ZephyrTestData) + { + var iteration = new Iteration + { + Parameters = new List() + }; + + foreach (var name in zephyrDataParameters.Keys) + { + iteration.Parameters.Add( + new Parameter + { + Name = name, + Value = zephyrDataParameters[name].Value + }); + } + + iterations.Add(iteration); + } + + _logger.LogInformation("Converted parameters: {@Parameters}", iterations); + + return iterations; + } + + private List ConvertParametersWithParameterType(List zephyrParameters) + { + var parameters = new List(); + + + foreach (var zephyrParameter in zephyrParameters) + { + parameters.Add( + new Parameter + { + Name = zephyrParameter.Name, + Value = zephyrParameter.Value + }); + } + + _logger.LogInformation("Converted parameters: {@Parameters}", parameters); + + return new List + { + new Iteration + { + Parameters = parameters + } + }; + } +} diff --git a/Migrators/ZephyrScaleServerExporter/Services/StepService.cs b/Migrators/ZephyrScaleServerExporter/Services/StepService.cs index 04aa8a5..5f35d60 100644 --- a/Migrators/ZephyrScaleServerExporter/Services/StepService.cs +++ b/Migrators/ZephyrScaleServerExporter/Services/StepService.cs @@ -10,19 +10,27 @@ public class StepService : IStepService { private readonly ILogger _logger; private readonly IAttachmentService _attachmentService; + private readonly IParameterService _parameterService; private readonly IClient _client; + private List _iterations; + private const string START_STEP_PARAMETER = "{"; + private const string END_STEP_PARAMETER = "}"; - public StepService(ILogger logger, IAttachmentService attachmentService, IClient client) + public StepService(ILogger logger, IAttachmentService attachmentService, + IParameterService parameterService, IClient client) { _logger = logger; _attachmentService = attachmentService; + _parameterService = parameterService; _client = client; } - public async Task> ConvertSteps(Guid testCaseId, ZephyrTestScript testScript) + public async Task ConvertSteps(Guid testCaseId, ZephyrTestScript testScript, List iterations) { _logger.LogInformation("Converting steps from test script {@TestScript}", testScript); + _iterations = iterations; + if (testScript.Steps != null) { var steps = testScript.Steps.OrderBy(s => s.Index).ToList(); @@ -47,29 +55,41 @@ public async Task> ConvertSteps(Guid testCaseId, ZephyrTestScript tes _logger.LogDebug("Steps: {@StepList}", stepList); - return stepList; + return new StepsData + { + Steps = stepList, + Iterations = _iterations + }; } if (testScript.Text != null) { - return new List + return new StepsData { - new() + Steps = new List { - Action = testScript.Text, - Expected = string.Empty, - TestData = string.Empty, - ActionAttachments = new List(), - ExpectedAttachments = new List(), - TestDataAttachments = new List() - } + new() + { + Action = testScript.Text, + Expected = string.Empty, + TestData = string.Empty, + ActionAttachments = new List(), + ExpectedAttachments = new List(), + TestDataAttachments = new List() + } + }, + Iterations = _iterations }; } - return new List(); + return new StepsData + { + Steps = new List(), + Iterations = _iterations + }; } - public async Task> ConvertSteps(Guid testCaseId, ZephyrArchivedTestScript testScript) + private async Task> ConvertArchivedSteps(Guid testCaseId, ZephyrArchivedTestScript testScript) { _logger.LogInformation("Converting steps from test script {@TestScript}", testScript); @@ -127,9 +147,9 @@ private async Task ConvertStep(Guid testCaseId, ZephyrStep step) var newStep = new Step { - Action = action.Description, - Expected = expected.Description, - TestData = testData.Description, + Action = AddParametersToStep(action.Description), + Expected = AddParametersToStep(expected.Description), + TestData = AddParametersToStep(testData.Description), ActionAttachments = new List(), ExpectedAttachments = new List(), TestDataAttachments = new List() @@ -245,19 +265,38 @@ private async Task> ConvertSharedSteps(Guid testCaseId, string testCa { _logger.LogInformation("Converting shared steps from test case key {testCaseKey}", testCaseKey); + var sharedStepsIterations = await _parameterService.ConvertParameters(testCaseKey); + _iterations = _parameterService.MergeIterations(_iterations, sharedStepsIterations); + try { var zephyrTestCase = await _client.GetTestCase(testCaseKey); return zephyrTestCase.TestScript != null ? - await ConvertSteps(testCaseId, zephyrTestCase.TestScript) : new List(); + (await ConvertSteps(testCaseId, zephyrTestCase.TestScript, _iterations)).Steps : new List(); } catch (Exception ex) { var zephyrArchivedTestCase = await _client.GetArchivedTestCase(testCaseKey); return zephyrArchivedTestCase.TestScript != null ? - await ConvertSteps(testCaseId, zephyrArchivedTestCase.TestScript) : new List(); + await ConvertArchivedSteps(testCaseId, zephyrArchivedTestCase.TestScript) : new List(); } } + + private string AddParametersToStep(string stepText) + { + if (stepText.Contains(START_STEP_PARAMETER) && stepText.Contains(END_STEP_PARAMETER)) + { + foreach (var iteration in _iterations) + { + foreach (var parameter in iteration.Parameters) + { + stepText = stepText.Replace(START_STEP_PARAMETER + parameter.Name + END_STEP_PARAMETER, $"<<<{parameter.Name}>>>"); + } + } + } + + return stepText; + } } diff --git a/Migrators/ZephyrScaleServerExporter/Services/TestCaseService.cs b/Migrators/ZephyrScaleServerExporter/Services/TestCaseService.cs index ae12ab2..6feef99 100644 --- a/Migrators/ZephyrScaleServerExporter/Services/TestCaseService.cs +++ b/Migrators/ZephyrScaleServerExporter/Services/TestCaseService.cs @@ -1,6 +1,5 @@ using Microsoft.Extensions.Logging; using Models; -using System.Linq; using ZephyrScaleServerExporter.Client; using ZephyrScaleServerExporter.Models; using Attribute = Models.Attribute; @@ -14,15 +13,17 @@ public class TestCaseService : ITestCaseService private readonly IClient _client; private readonly IStepService _stepService; private readonly IAttachmentService _attachmentService; + private readonly IParameterService _parameterService; public const int _duration = 10000; public TestCaseService(ILogger logger, IClient client, IStepService stepService, - IAttachmentService attachmentService) + IAttachmentService attachmentService, IParameterService parameterService) { _logger = logger; _client = client; _stepService = stepService; _attachmentService = attachmentService; + _parameterService = parameterService; } public async Task ConvertTestCases(SectionData sectionData, Dictionary attributeMap) @@ -50,8 +51,17 @@ public async Task ConvertTestCases(SectionData sectionData, Dictio attachments.Add(fileName); } - var steps = zephyrTestCase.TestScript != null ? - await _stepService.ConvertSteps(testCaseId, zephyrTestCase.TestScript) : new List(); + var iterations = await _parameterService.ConvertParameters(zephyrTestCase.Key); + + var steps = new List(); + + if (zephyrTestCase.TestScript != null) + { + var stepsData = await _stepService.ConvertSteps(testCaseId, zephyrTestCase.TestScript, iterations); + + steps = stepsData.Steps; + iterations = stepsData.Iterations; + } steps.ForEach(s => { @@ -145,7 +155,7 @@ public async Task ConvertTestCases(SectionData sectionData, Dictio Attributes = attributes, Tags = zephyrTestCase.Labels ?? new List(), Attachments = attachments, - Iterations = new List(), + Iterations = iterations, Links = links, Name = zephyrTestCase.Name, SectionId = sectionId