From bb6a964dec15d4f06487148ae39ec5ae16bdbbe9 Mon Sep 17 00:00:00 2001 From: "pavel.butuzov" Date: Tue, 14 Nov 2023 09:39:54 +0300 Subject: [PATCH 1/4] Added PractiTestExporter. --- .github/workflows/release.yaml | 50 ++- .github/workflows/validate.yaml | 2 + Migrators/Migrators.sln | 28 +- Migrators/PractiTestExporter/App.cs | 25 ++ Migrators/PractiTestExporter/Client/Client.cs | 226 ++++++++++ .../PractiTestExporter/Client/IClient.cs | 15 + .../Models/AttributeData.cs | 9 + .../PractiTestExporter/Models/Constants.cs | 10 + .../Models/PractiTestAttachment.cs | 27 ++ .../Models/PractiTestCustomField.cs | 57 +++ .../Models/PractiTestProject.cs | 24 ++ .../Models/PractiTestStep.cs | 42 ++ .../Models/PractiTestTestCase.cs | 63 +++ .../PractiTestExporter/Models/TestCaseData.cs | 9 + .../PractiTestExporter.csproj | 35 ++ Migrators/PractiTestExporter/Program.cs | 73 ++++ Migrators/PractiTestExporter/Readme.md | 56 +++ .../Services/AttachmentService.cs | 44 ++ .../Services/AttributeService.cs | 69 ++++ .../Services/ExportService.cs | 75 ++++ .../Services/IAttachmentService.cs | 8 + .../Services/IAttributeService.cs | 8 + .../Services/IExportService.cs | 6 + .../Services/ITestCaseService.cs | 8 + .../Services/TestCaseService.cs | 261 ++++++++++++ .../PractiTestExporter/practitest.config.json | 8 + .../AttachmentServiceTests.cs | 134 ++++++ .../AttributeServiceTests.cs | 145 +++++++ .../ExportServiceTests.cs | 279 +++++++++++++ .../PractiTestExporterTests/GlobalUsings.cs | 1 + .../PractiTestExporterTests.csproj | 32 ++ .../TestCaseServiceTests.cs | 386 ++++++++++++++++++ Migrators/TestLinkExporter/Readme.md | 6 +- 33 files changed, 2207 insertions(+), 14 deletions(-) create mode 100644 Migrators/PractiTestExporter/App.cs create mode 100644 Migrators/PractiTestExporter/Client/Client.cs create mode 100644 Migrators/PractiTestExporter/Client/IClient.cs create mode 100644 Migrators/PractiTestExporter/Models/AttributeData.cs create mode 100644 Migrators/PractiTestExporter/Models/Constants.cs create mode 100644 Migrators/PractiTestExporter/Models/PractiTestAttachment.cs create mode 100644 Migrators/PractiTestExporter/Models/PractiTestCustomField.cs create mode 100644 Migrators/PractiTestExporter/Models/PractiTestProject.cs create mode 100644 Migrators/PractiTestExporter/Models/PractiTestStep.cs create mode 100644 Migrators/PractiTestExporter/Models/PractiTestTestCase.cs create mode 100644 Migrators/PractiTestExporter/Models/TestCaseData.cs create mode 100644 Migrators/PractiTestExporter/PractiTestExporter.csproj create mode 100644 Migrators/PractiTestExporter/Program.cs create mode 100644 Migrators/PractiTestExporter/Readme.md create mode 100644 Migrators/PractiTestExporter/Services/AttachmentService.cs create mode 100644 Migrators/PractiTestExporter/Services/AttributeService.cs create mode 100644 Migrators/PractiTestExporter/Services/ExportService.cs create mode 100644 Migrators/PractiTestExporter/Services/IAttachmentService.cs create mode 100644 Migrators/PractiTestExporter/Services/IAttributeService.cs create mode 100644 Migrators/PractiTestExporter/Services/IExportService.cs create mode 100644 Migrators/PractiTestExporter/Services/ITestCaseService.cs create mode 100644 Migrators/PractiTestExporter/Services/TestCaseService.cs create mode 100644 Migrators/PractiTestExporter/practitest.config.json create mode 100644 Migrators/PractiTestExporterTests/AttachmentServiceTests.cs create mode 100644 Migrators/PractiTestExporterTests/AttributeServiceTests.cs create mode 100644 Migrators/PractiTestExporterTests/ExportServiceTests.cs create mode 100644 Migrators/PractiTestExporterTests/GlobalUsings.cs create mode 100644 Migrators/PractiTestExporterTests/PractiTestExporterTests.csproj create mode 100644 Migrators/PractiTestExporterTests/TestCaseServiceTests.cs diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 70afee3..6318925 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -13,6 +13,7 @@ env: ZEPHYR_SQUAD_DIR: ./Migrators/ZephyrSquadExporter XRAY_DIR: ./Migrators/XRayExporter TESTLINK_DIR: ./Migrators/TestLinkExporter + PRACTITEST_DIR: ./Migrators/PractiTestExporter jobs: importer_build: @@ -342,4 +343,51 @@ jobs: file: publish/${{ matrix.artifact_name }} asset_name: ${{ matrix.asset_name }} tag: ${{ github.ref }} - overwrite: true \ No newline at end of file + overwrite: true + + practitest_build: + needs: testlink_build + runs-on: ubuntu-latest + strategy: + matrix: + include: + - os: win-x64 + artifact_name: PractiTestExporter.exe + asset_name: PractiTestExporter-win-x64-${{ github.event.release.tag_name }}.exe + - os: linux-x64 + artifact_name: PractiTestExporter + asset_name: PractiTestExporter-linux-x64-${{ github.event.release.tag_name }} + - os: osx-x64 + artifact_name: PractiTestExporter + asset_name: PractiTestExporter-osx-x64-${{ github.event.release.tag_name }} + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 7 + + - name: Restore dependencies + run: dotnet restore ${{ env.PRACTITEST_DIR }} + + - name: Publish project + run: | + dotnet publish \ + -r ${{ matrix.os }} \ + --configuration Release \ + --self-contained true \ + --output ./publish \ + --no-restore ${{ env.PRACTITEST_DIR }} + + - name: Upload binaries to release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: publish/${{ matrix.artifact_name }} + asset_name: ${{ matrix.asset_name }} + tag: ${{ github.ref }} + overwrite: true \ No newline at end of file diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml index 03efdeb..3bd7810 100644 --- a/.github/workflows/validate.yaml +++ b/.github/workflows/validate.yaml @@ -15,6 +15,7 @@ jobs: ./Migrators/ZephyrSquadExporter, ./Migrators/XRayExporter, ./Migrators/TestLinkExporter, + ./Migrators/PractiTestExporter, ./Migrators/Importer ] steps: @@ -43,6 +44,7 @@ jobs: ./Migrators/ZephyrSquadExporterTests, ./Migrators/XRayExporterTests, ./Migrators/TestLinkExporterTests, + ./Migrators/PractiTestExporterTests, ./Migrators/ImporterTests ] steps: diff --git a/Migrators/Migrators.sln b/Migrators/Migrators.sln index 82d3d3f..bc7860b 100644 --- a/Migrators/Migrators.sln +++ b/Migrators/Migrators.sln @@ -37,19 +37,19 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZephyrSquadExporterTests", "ZephyrSquadExporterTests\ZephyrSquadExporterTests.csproj", "{C2B65002-89C3-4FD6-A945-87379D552098}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestLinkExporter", "TestLinkExporter\TestLinkExporter.csproj", "{EDB0D0A9-2B1A-46FB-B0BE-F8166F497BF1}" - ProjectSection(ProjectDependencies) = postProject - {6ABE461F-B644-40A5-A525-4F59ED1C177A} = {6ABE461F-B644-40A5-A525-4F59ED1C177A} - {C03F7958-C302-4F57-B158-E1F0E8A1A302} = {C03F7958-C302-4F57-B158-E1F0E8A1A302} - EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestLinkExporterTests", "TestLinkExporterTests\TestLinkExporterTests.csproj", "{87D89020-4060-4DA3-BD90-99CA1DBEBD6C}" - ProjectSection(ProjectDependencies) = postProject - {EDB0D0A9-2B1A-46FB-B0BE-F8166F497BF1} = {EDB0D0A9-2B1A-46FB-B0BE-F8166F497BF1} - EndProjectSection +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestLinkExporterTests", "TestLinkExporterTests\TestLinkExporterTests.csproj", "{87D89020-4060-4DA3-BD90-99CA1DBEBD6C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XRayExporter", "XRayExporter\XRayExporter.csproj", "{1E3A8E07-1023-4A40-90DF-1A2CA6BB707C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XRayExporter", "XRayExporter\XRayExporter.csproj", "{1E3A8E07-1023-4A40-90DF-1A2CA6BB707C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XRayExporterTests", "XRayExporterTests\XRayExporterTests.csproj", "{563D5041-6E07-4D52-BBB9-C87245604E6F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XRayExporterTests", "XRayExporterTests\XRayExporterTests.csproj", "{563D5041-6E07-4D52-BBB9-C87245604E6F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PractiTestExporter", "PractiTestExporter\PractiTestExporter.csproj", "{B90D8A9F-CFCB-4F02-8B76-4C082FFA3D06}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PractiTestExporterTests", "PractiTestExporterTests\PractiTestExporterTests.csproj", "{AB081068-0DE0-4408-A858-5109CCF0C3B4}" + ProjectSection(ProjectDependencies) = postProject + {B90D8A9F-CFCB-4F02-8B76-4C082FFA3D06} = {B90D8A9F-CFCB-4F02-8B76-4C082FFA3D06} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -121,6 +121,14 @@ Global {563D5041-6E07-4D52-BBB9-C87245604E6F}.Debug|Any CPU.Build.0 = Debug|Any CPU {563D5041-6E07-4D52-BBB9-C87245604E6F}.Release|Any CPU.ActiveCfg = Release|Any CPU {563D5041-6E07-4D52-BBB9-C87245604E6F}.Release|Any CPU.Build.0 = Release|Any CPU + {B90D8A9F-CFCB-4F02-8B76-4C082FFA3D06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B90D8A9F-CFCB-4F02-8B76-4C082FFA3D06}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B90D8A9F-CFCB-4F02-8B76-4C082FFA3D06}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B90D8A9F-CFCB-4F02-8B76-4C082FFA3D06}.Release|Any CPU.Build.0 = Release|Any CPU + {AB081068-0DE0-4408-A858-5109CCF0C3B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB081068-0DE0-4408-A858-5109CCF0C3B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB081068-0DE0-4408-A858-5109CCF0C3B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB081068-0DE0-4408-A858-5109CCF0C3B4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Migrators/PractiTestExporter/App.cs b/Migrators/PractiTestExporter/App.cs new file mode 100644 index 0000000..afc7740 --- /dev/null +++ b/Migrators/PractiTestExporter/App.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.Logging; +using PractiTestExporter.Services; + +namespace PractiTestExporter; + +public class App +{ + private readonly ILogger _logger; + private readonly IExportService _service; + + public App(ILogger logger, IExportService service) + { + _logger = logger; + _service = service; + } + + public void Run(string[] args) + { + _logger.LogInformation("Starting application"); + + _service.ExportProject().Wait(); + + _logger.LogInformation("Ending application"); + } +} diff --git a/Migrators/PractiTestExporter/Client/Client.cs b/Migrators/PractiTestExporter/Client/Client.cs new file mode 100644 index 0000000..f964ede --- /dev/null +++ b/Migrators/PractiTestExporter/Client/Client.cs @@ -0,0 +1,226 @@ +using System.Text.Json; +using PractiTestExporter.Models; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; + +namespace PractiTestExporter.Client; + +public class Client : IClient +{ + private readonly ILogger _logger; + private readonly HttpClient _httpClient; + private readonly string _projectId; + private const int requestDelay = 2; + + public Client(ILogger logger, IConfiguration configuration) + { + _logger = logger; + + var section = configuration.GetSection("practiTest"); + var url = section["url"]; + if (string.IsNullOrEmpty(url)) + { + throw new ArgumentException("Url is not specified"); + } + + var token = section["token"]; + if (string.IsNullOrEmpty(token)) + { + throw new ArgumentException("Token is not specified"); + } + + var projectId = section["projectId"]; + if (string.IsNullOrEmpty(projectId)) + { + throw new ArgumentException("Project name is not specified"); + } + + _projectId = projectId; + _httpClient = new HttpClient(); + _httpClient.BaseAddress = new Uri(url); + _httpClient.DefaultRequestHeaders.Add("PTToken", token); + } + + public async Task GetProject() + { + await Task.Delay(TimeSpan.FromSeconds(requestDelay)); + + _logger.LogInformation("Getting project with id {Id}", _projectId); + + var response = await _httpClient.GetAsync($"api/v2/projects/{_projectId}.json"); + if (!response.IsSuccessStatusCode) + { + _logger.LogError("Failed to get project. Status code: {StatusCode}. Response: {Response}", + response.StatusCode, await response.Content.ReadAsStringAsync()); + + throw new Exception($"Failed to get project. Status code: {response.StatusCode}"); + } + + var content = await response.Content.ReadAsStringAsync(); + var project = JsonSerializer.Deserialize(content); + + if (project != null) return project; + + _logger.LogError("Project not found"); + + throw new Exception("Project not found"); + } + + public async Task> GetTestCases() + { + await Task.Delay(TimeSpan.FromSeconds(requestDelay)); + + _logger.LogInformation("Getting test cases from project {Id}", _projectId); + + var response = + await _httpClient.GetAsync($"api/v2/projects/{_projectId}/tests.json"); + if (!response.IsSuccessStatusCode) + { + _logger.LogError( + "Failed to get test case ids from project {Id}. Status code: {StatusCode}. Response: {Response}", + _projectId, response.StatusCode, await response.Content.ReadAsStringAsync()); + + throw new Exception( + $"Failed to get test case ids from project {_projectId}. Status code: {response.StatusCode}"); + } + + var content = await response.Content.ReadAsStringAsync(); + var testCases = JsonSerializer.Deserialize(content); + + return testCases is { Data.Count: 0 } + ? new List() + : testCases.Data; + } + + public async Task GetTestCaseById(string id) + { + await Task.Delay(TimeSpan.FromSeconds(requestDelay)); + + _logger.LogInformation("Getting test case by id {Id}", id); + + var response = + await _httpClient.GetAsync($"api/v2/projects/{_projectId}/tests/{id}.json"); + if (!response.IsSuccessStatusCode) + { + _logger.LogError( + "Failed to get test case by id {Id}. Status code: {StatusCode}. Response: {Response}", + id, response.StatusCode, await response.Content.ReadAsStringAsync()); + + throw new Exception( + $"Failed to get test case by id {id}. Status code: {response.StatusCode}"); + } + + var content = await response.Content.ReadAsStringAsync(); + var testCase = JsonSerializer.Deserialize(content); + + return testCase.Data; + } + + public async Task> GetStepsByTestCaseId(string testCaseId) + { + await Task.Delay(TimeSpan.FromSeconds(requestDelay)); + + _logger.LogInformation("Getting steps for test case with id {Id}", testCaseId); + + var response = await _httpClient.GetAsync($"api/v2/projects/{_projectId}/steps.json?test-ids={testCaseId}"); + if (!response.IsSuccessStatusCode) + { + _logger.LogError( + "Failed to get steps for test case with id {TestCaseId}. Status code: {StatusCode}. Response: {Response}", + testCaseId, response.StatusCode, await response.Content.ReadAsStringAsync()); + + throw new Exception( + $"Failed to get steps for test case with id {testCaseId}. Status code: {response.StatusCode}"); + } + + var content = await response.Content.ReadAsStringAsync(); + var steps = JsonSerializer.Deserialize(content); + + return steps is { Data.Count: 0 } + ? new List() + : steps.Data; + } + + public async Task> GetAttachmentsByEntityId(string entityType, string entityId) + { + await Task.Delay(TimeSpan.FromSeconds(requestDelay)); + + _logger.LogInformation("Getting attachments for {EntityType} with id {EntityId}", entityType, entityId); + + var response = await _httpClient.GetAsync($"api/v2/projects/{_projectId}/attachments.json?entity={entityType}&entity-id={entityId}"); + + if (!response.IsSuccessStatusCode) + { + _logger.LogError( + "Failed to get attachments for {EntityType} with id {EntityId}. Status code: {StatusCode}. Response: {Response}", + entityType, entityId, response.StatusCode, await response.Content.ReadAsStringAsync()); + + throw new Exception( + $"Failed to get attachments for {entityType} with id {entityId}. Status code: {response.StatusCode}"); + } + + var content = await response.Content.ReadAsStringAsync(); + var attachments = JsonSerializer.Deserialize(content); + + return attachments is { Data.Count: 0 } + ? new List() + : attachments.Data; + } + + public async Task DownloadAttachmentById(string id) + { + await Task.Delay(TimeSpan.FromSeconds(requestDelay)); + + _logger.LogInformation("Downloading attachment by id {Id}", id); + + return await _httpClient.GetByteArrayAsync($"api/v2/projects/{_projectId}/attachments/{id}"); + } + + public async Task> GetCustomFields() + { + await Task.Delay(TimeSpan.FromSeconds(requestDelay)); + + _logger.LogInformation("Getting custom fields by project id {ProjectId}", _projectId); + + var response = await _httpClient.GetAsync($"api/v2/projects/{_projectId}/custom_fields.json"); + if (!response.IsSuccessStatusCode) + { + _logger.LogError( + "Failed to get custom fields by project id {ProjectId}. Status code: {StatusCode}. Response: {Response}", + _projectId, response.StatusCode, await response.Content.ReadAsStringAsync()); + + throw new Exception( + $"Failed to get custom fields by project id {_projectId}. Status code: {response.StatusCode}"); + } + + var content = await response.Content.ReadAsStringAsync(); + var customFields = JsonSerializer.Deserialize(content); + + return customFields is { Data.Count: 0 } + ? new List() + : customFields.Data; + } + + public async Task GetListCustomFieldById(string id) + { + await Task.Delay(TimeSpan.FromSeconds(requestDelay)); + + _logger.LogInformation("Getting custom field by id {Id}", id); + + var response = await _httpClient.GetAsync($"api/v2/projects/{_projectId}/custom_fields//{id}.json"); + if (!response.IsSuccessStatusCode) + { + _logger.LogError( + "Failed to get custom field by id {Id}. Status code: {StatusCode}. Response: {Response}", + id, response.StatusCode, await response.Content.ReadAsStringAsync()); + + throw new Exception( + $"Failed to get custom field by id {id}. Status code: {response.StatusCode}"); + } + + var content = await response.Content.ReadAsStringAsync(); + var customField = JsonSerializer.Deserialize(content); + + return customField.Data; + } +} diff --git a/Migrators/PractiTestExporter/Client/IClient.cs b/Migrators/PractiTestExporter/Client/IClient.cs new file mode 100644 index 0000000..3bcebb1 --- /dev/null +++ b/Migrators/PractiTestExporter/Client/IClient.cs @@ -0,0 +1,15 @@ +using PractiTestExporter.Models; + +namespace PractiTestExporter.Client; + +public interface IClient +{ + Task GetProject(); + Task> GetTestCases(); + Task GetTestCaseById(string id); + Task> GetStepsByTestCaseId(string testCaseId); + Task> GetAttachmentsByEntityId(string entityType, string entityId); + Task DownloadAttachmentById(string id); + Task> GetCustomFields(); + Task GetListCustomFieldById(string id); +} diff --git a/Migrators/PractiTestExporter/Models/AttributeData.cs b/Migrators/PractiTestExporter/Models/AttributeData.cs new file mode 100644 index 0000000..f6c767b --- /dev/null +++ b/Migrators/PractiTestExporter/Models/AttributeData.cs @@ -0,0 +1,9 @@ +using Attribute = Models.Attribute; + +namespace PractiTestExporter.Models; + +public class AttributeData +{ + public List Attributes { get; set; } + public Dictionary AttributeMap { get; set; } +} diff --git a/Migrators/PractiTestExporter/Models/Constants.cs b/Migrators/PractiTestExporter/Models/Constants.cs new file mode 100644 index 0000000..7ee0b12 --- /dev/null +++ b/Migrators/PractiTestExporter/Models/Constants.cs @@ -0,0 +1,10 @@ +namespace PractiTestExporter.Models; + +public class Constants +{ + public const string ListCustomFieldType = "list"; + public const string MultiListCustomFieldType = "multilist"; + public const string DateCustomFieldType = "date"; + public const string TestCaseEntityType = "test"; + public const string StepEntityType = "step"; +} diff --git a/Migrators/PractiTestExporter/Models/PractiTestAttachment.cs b/Migrators/PractiTestExporter/Models/PractiTestAttachment.cs new file mode 100644 index 0000000..723b134 --- /dev/null +++ b/Migrators/PractiTestExporter/Models/PractiTestAttachment.cs @@ -0,0 +1,27 @@ +using System.Text.Json.Serialization; + +namespace PractiTestExporter.Models; + +public class AttachmentAttributes +{ + [JsonPropertyName("name")] + public string Name { get; set; } +} + +public class PractiTestAttachment +{ + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("attributes")] + public AttachmentAttributes Attributes { get; set; } +} + +public class PractiTestAttachments +{ + [JsonPropertyName("data")] + public List Data { get; set; } +} diff --git a/Migrators/PractiTestExporter/Models/PractiTestCustomField.cs b/Migrators/PractiTestExporter/Models/PractiTestCustomField.cs new file mode 100644 index 0000000..e54c7c5 --- /dev/null +++ b/Migrators/PractiTestExporter/Models/PractiTestCustomField.cs @@ -0,0 +1,57 @@ +using System.Text.Json.Serialization; + +namespace PractiTestExporter.Models; + +public class CustomFieldAttributes +{ + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("field-format")] + public string FieldFormat { get; set; } + + [JsonPropertyName("project-id")] + public int ProjectId { get; set; } +} + +public class ListCustomFieldAttributes : CustomFieldAttributes +{ + [JsonPropertyName("possible-values")] + public List PossibleValues { get; set; } +} + +public class PractiTestCustomField +{ + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("attributes")] + public CustomFieldAttributes Attributes { get; set; } +} + +public class ListPractiTestCustomField +{ + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("attributes")] + public ListCustomFieldAttributes Attributes { get; set; } +} + +public class PractiTestCustomFields +{ + [JsonPropertyName("data")] + public List Data { get; set; } +} + +public class SinglePractiTestCustomField +{ + [JsonPropertyName("data")] + public ListPractiTestCustomField Data { get; set; } +} diff --git a/Migrators/PractiTestExporter/Models/PractiTestProject.cs b/Migrators/PractiTestExporter/Models/PractiTestProject.cs new file mode 100644 index 0000000..3707ca0 --- /dev/null +++ b/Migrators/PractiTestExporter/Models/PractiTestProject.cs @@ -0,0 +1,24 @@ +using System.Text.Json.Serialization; + +namespace PractiTestExporter.Models; + +public class ProjectAttributes +{ + [JsonPropertyName("name")] + public string Name { get; set; } +} + +public class ProjectData +{ + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("attributes")] + public ProjectAttributes Attributes { get; set; } +} + +public class PractiTestProject +{ + [JsonPropertyName("data")] + public ProjectData Data { get; set; } +} diff --git a/Migrators/PractiTestExporter/Models/PractiTestStep.cs b/Migrators/PractiTestExporter/Models/PractiTestStep.cs new file mode 100644 index 0000000..9345371 --- /dev/null +++ b/Migrators/PractiTestExporter/Models/PractiTestStep.cs @@ -0,0 +1,42 @@ +using System.Text.Json.Serialization; + +namespace PractiTestExporter.Models; + +public class StepAttributes +{ + [JsonPropertyName("test-id")] + public int TestId { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("description")] + public string Description { get; set; } + + [JsonPropertyName("expected-results")] + public string ExpectedResults { get; set; } + + [JsonPropertyName("position")] + public int Position { get; set; } + + [JsonPropertyName("test-to-call-id")] + public int? TestToCallId { get; set; } +} + +public class PractiTestStep +{ + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("attributes")] + public StepAttributes Attributes { get; set; } +} + +public class PractiTestSteps +{ + [JsonPropertyName("data")] + public List Data { get; set; } +} diff --git a/Migrators/PractiTestExporter/Models/PractiTestTestCase.cs b/Migrators/PractiTestExporter/Models/PractiTestTestCase.cs new file mode 100644 index 0000000..c4fbc88 --- /dev/null +++ b/Migrators/PractiTestExporter/Models/PractiTestTestCase.cs @@ -0,0 +1,63 @@ +using System.Text.Json.Serialization; + +namespace PractiTestExporter.Models; + +public class TestCaseAttributes +{ + [JsonPropertyName("project-id")] + public int ProjectId { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("description")] + public string Description { get; set; } + + [JsonPropertyName("preconditions")] + public string Preconditions { get; set; } + + [JsonPropertyName("steps-count")] + public int StepsCount { get; set; } + + [JsonPropertyName("status")] + public string Status { get; set; } + + [JsonPropertyName("priority")] + public object Priority { get; set; } + + [JsonPropertyName("duration-estimate")] + public string DurationEstimate { get; set; } + + [JsonPropertyName("test-type")] + public string TestType { get; set; } + + [JsonPropertyName("tags")] + public List Tags { get; set; } + + [JsonPropertyName("custom-fields")] + public Dictionary CustomFields { get; set; } +} + +public class PractiTestTestCase +{ + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("attributes")] + public TestCaseAttributes Attributes { get; set; } +} + +public class PractiTestTestCases +{ + [JsonPropertyName("data")] + public List Data { get; set; } +} + +public class SinglePractiTestTestCase +{ + [JsonPropertyName("data")] + public PractiTestTestCase Data { get; set; } +} diff --git a/Migrators/PractiTestExporter/Models/TestCaseData.cs b/Migrators/PractiTestExporter/Models/TestCaseData.cs new file mode 100644 index 0000000..a833789 --- /dev/null +++ b/Migrators/PractiTestExporter/Models/TestCaseData.cs @@ -0,0 +1,9 @@ +using Models; + +namespace PractiTestExporter.Models; + +public class TestCaseData +{ + public List TestCases { get; set; } + public List SharedSteps { get; set; } +} diff --git a/Migrators/PractiTestExporter/PractiTestExporter.csproj b/Migrators/PractiTestExporter/PractiTestExporter.csproj new file mode 100644 index 0000000..0f33b8c --- /dev/null +++ b/Migrators/PractiTestExporter/PractiTestExporter.csproj @@ -0,0 +1,35 @@ + + + + Exe + net7.0 + enable + enable + true + true + win-x64;linux-x64;osx-x64 + + + + + + + + + + + + + + + + + + + + + Always + + + + diff --git a/Migrators/PractiTestExporter/Program.cs b/Migrators/PractiTestExporter/Program.cs new file mode 100644 index 0000000..1a9e3a7 --- /dev/null +++ b/Migrators/PractiTestExporter/Program.cs @@ -0,0 +1,73 @@ +using JsonWriter; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Events; +using Serilog.Expressions; +using Serilog.Settings.Configuration; +using PractiTestExporter.Client; +using PractiTestExporter.Services; + +namespace PractiTestExporter +{ + internal class Program + { + static void Main(string[] args) + { + using var host = CreateHostBuilder(args).Build(); + using var scope = host.Services.CreateScope(); + + var services = scope.ServiceProvider; + + try + { + services.GetRequiredService().Run(args); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + } + + static IHostBuilder CreateHostBuilder(string[] strings) + { + var options = new ConfigurationReaderOptions(typeof(ConsoleLoggerConfigurationExtensions).Assembly, + typeof(SerilogExpression).Assembly); + + return Host.CreateDefaultBuilder() + .UseSerilog((context, services, configuration) => configuration + .ReadFrom.Configuration(context.Configuration, options) + .ReadFrom.Services(services) + .Enrich.FromLogContext() + .MinimumLevel.Debug() + .WriteTo.File("logs/log.txt", + restrictedToMinimumLevel: LogEventLevel.Debug, + outputTemplate: + "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}" + ) + .WriteTo.Console(LogEventLevel.Information) + ) + .ConfigureServices((_, services) => + { + services.AddSingleton(); + services.AddSingleton(SetupConfiguration()); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + }); + } + + private static IConfiguration SetupConfiguration() + { + return new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("practitest.config.json") + .AddEnvironmentVariables() + .Build(); + } + } +} diff --git a/Migrators/PractiTestExporter/Readme.md b/Migrators/PractiTestExporter/Readme.md new file mode 100644 index 0000000..6099451 --- /dev/null +++ b/Migrators/PractiTestExporter/Readme.md @@ -0,0 +1,56 @@ +# PractiTest Exporter + +You can use this exporter to export your test cases from PractiTest. + +## Download + +You can download the latest version of the PractiTestExporter from the [releases](https://github.com/testit-tms/migrators/releases/latest) page. + +## How to use + +1. Configure connection in the `practitest.config.json` file and save it in the PractiTestExporter location. + +```json +{ + "resultPath": "/Users/user01/Documents/importer", + "practiTest": { + "url": "https://prod-api.practitest.app", + "token": "a7b9bea53f1e7a6ef7d3052969b55926680bc13b", + "projectId": "15467" + } +} +``` + +Where: + +- resultPath - path to the folder where the results will be saved +- practiTest.url - PractiTest API url +- practiTest.token - token for access to the PractiTest +- practiTest.projectName - name of the project in the PractiTest + +1. Run the exporter with the following command: + +```bash +.\PractiTestExporter +``` + +3. Check the results in the folder specified in the `resultPath` parameter. + +4. Use the results in the [importer](https://github.com/testit-tms/migrators/tree/main/Migrators/Importer/Readme.md). + +## Contributing + +You can help to develop the project. Any contributions are **greatly appreciated**. + +- If you have suggestions for adding or removing projects, feel free + to [open an issue](https://github.com/testit-tms/migrators/issues/new) to discuss it, or create a direct pull + request after you edit the *README.md* file with necessary changes. +- Make sure to check your spelling and grammar. +- Create individual PR for each suggestion. +- Read the [Code Of Conduct](https://github.com/testit-tms/migrators/blob/main/CODE_OF_CONDUCT.md) before posting + your first idea as well. + +## License + +Distributed under the Apache-2.0 License. +See [LICENSE](https://github.com/testit-tms/migrators/blob/main/LICENSE) for more information. diff --git a/Migrators/PractiTestExporter/Services/AttachmentService.cs b/Migrators/PractiTestExporter/Services/AttachmentService.cs new file mode 100644 index 0000000..c9b1549 --- /dev/null +++ b/Migrators/PractiTestExporter/Services/AttachmentService.cs @@ -0,0 +1,44 @@ +using PractiTestExporter.Models; +using JsonWriter; +using Microsoft.Extensions.Logging; +using PractiTestExporter.Client; + +namespace PractiTestExporter.Services; + +public class AttachmentService : IAttachmentService +{ + private readonly ILogger _logger; + private readonly IClient _client; + private readonly IWriteService _writeService; + + public AttachmentService(ILogger logger, IClient client, IWriteService writeService) + { + _logger = logger; + _client = client; + _writeService = writeService; + } + + public async Task> DownloadAttachments(string entityType, string id, Guid workItemId) + { + _logger.LogInformation("Getting attachments by {EntityType} id {Id}", entityType, id); + + var names = new List(); + + var practiTestAttachments = await _client.GetAttachmentsByEntityId(entityType, id); + + foreach (var practiTestAttachment in practiTestAttachments) + { + _logger.LogInformation("Downloading attachment {Name} by id: {Id}", practiTestAttachment.Attributes.Name, practiTestAttachment.Id); + + var contentType = await _client.DownloadAttachmentById(practiTestAttachment.Id); + + var name = await _writeService.WriteAttachment(workItemId, contentType, practiTestAttachment.Attributes.Name); + + names.Add(name); + } + + _logger.LogDebug("Ending downloading attachments: {@Names}", names); + + return names; + } +} diff --git a/Migrators/PractiTestExporter/Services/AttributeService.cs b/Migrators/PractiTestExporter/Services/AttributeService.cs new file mode 100644 index 0000000..236eb12 --- /dev/null +++ b/Migrators/PractiTestExporter/Services/AttributeService.cs @@ -0,0 +1,69 @@ +using Microsoft.Extensions.Logging; +using Models; +using PractiTestExporter.Client; +using PractiTestExporter.Models; +using Attribute = Models.Attribute; +using Constants = PractiTestExporter.Models.Constants; + +namespace PractiTestExporter.Services; + +public class AttributeService : IAttributeService +{ + private readonly ILogger _logger; + private readonly IClient _client; + + public AttributeService(ILogger logger, IClient client) + { + _logger = logger; + _client = client; + } + + public async Task ConvertCustomAttributes() + { + _logger.LogInformation("Getting custom attributes"); + + var attributes = new List(); + var attributeMap = new Dictionary(); + + var customFields = await _client.GetCustomFields(); + + foreach (var customField in customFields) + { + var attribute = new Attribute + { + Id = Guid.NewGuid(), + Name = customField.Attributes.Name, + IsActive = true, + IsRequired = false, + Type = ConvertType(customField.Attributes.FieldFormat), + Options = new List() + }; + + if (attribute.Type == AttributeType.Options) + { + var listCustomField = await _client.GetListCustomFieldById(customField.Id); + + attribute.Options = listCustomField.Attributes.PossibleValues; + } + + attributes.Add(attribute); + attributeMap.Add(customField.Id, attribute.Id); + } + + return new AttributeData + { + Attributes = attributes, + AttributeMap = attributeMap, + }; + } + + private static AttributeType ConvertType(string type) + { + return type switch + { + Constants.ListCustomFieldType or Constants.MultiListCustomFieldType => AttributeType.Options, + Constants.DateCustomFieldType => AttributeType.Datetime, + _ => AttributeType.String + }; + } +} diff --git a/Migrators/PractiTestExporter/Services/ExportService.cs b/Migrators/PractiTestExporter/Services/ExportService.cs new file mode 100644 index 0000000..0bc3a0e --- /dev/null +++ b/Migrators/PractiTestExporter/Services/ExportService.cs @@ -0,0 +1,75 @@ +using PractiTestExporter.Client; +using Microsoft.Extensions.Logging; +using Models; +using JsonWriter; + +namespace PractiTestExporter.Services; + +public class ExportService : IExportService +{ + private readonly ILogger _logger; + private readonly IClient _client; + private readonly IWriteService _writeService; + private readonly ITestCaseService _testCaseService; + private readonly IAttributeService _attributeService; + private const string SectionName = "PractiTest"; + + public ExportService(ILogger logger, IClient client, + IWriteService writeService, ITestCaseService testCaseService, IAttributeService attributeService) + { + _logger = logger; + _client = client; + _writeService = writeService; + _testCaseService = testCaseService; + _attributeService = attributeService; + } + + public async Task ExportProject() + { + _logger.LogInformation("Starting export"); + + var project = await _client.GetProject(); + + var section = new Section + { + Id = Guid.NewGuid(), + Name = SectionName, + PreconditionSteps = new List(), + PostconditionSteps = new List(), + Sections = new List
() + }; + + var attributeData = await _attributeService.ConvertCustomAttributes(); + var testCaseData = await _testCaseService.ConvertTestCases( + section.Id, + attributeData.AttributeMap + ); + + foreach (var sharedStep in testCaseData.SharedSteps) + { + await _writeService.WriteSharedStep(sharedStep); + } + + foreach (var testCase in testCaseData.TestCases) + { + await _writeService.WriteTestCase(testCase); + } + + var mainJson = new Root + { + ProjectName = project.Data.Attributes.Name, + Sections = new List
{ section }, + TestCases = testCaseData.TestCases + .Select(t => t.Id) + .ToList(), + SharedSteps = testCaseData.SharedSteps + .Select(s => s.Id) + .ToList(), + Attributes = attributeData.Attributes, + }; + + await _writeService.WriteMainJson(mainJson); + + _logger.LogInformation("Ending export"); + } +} diff --git a/Migrators/PractiTestExporter/Services/IAttachmentService.cs b/Migrators/PractiTestExporter/Services/IAttachmentService.cs new file mode 100644 index 0000000..d7508b0 --- /dev/null +++ b/Migrators/PractiTestExporter/Services/IAttachmentService.cs @@ -0,0 +1,8 @@ +using PractiTestExporter.Models; + +namespace PractiTestExporter.Services; + +public interface IAttachmentService +{ + Task> DownloadAttachments(string entityType, string id, Guid workItemId); +} diff --git a/Migrators/PractiTestExporter/Services/IAttributeService.cs b/Migrators/PractiTestExporter/Services/IAttributeService.cs new file mode 100644 index 0000000..6c47868 --- /dev/null +++ b/Migrators/PractiTestExporter/Services/IAttributeService.cs @@ -0,0 +1,8 @@ +using PractiTestExporter.Models; + +namespace PractiTestExporter.Services; + +public interface IAttributeService +{ + Task ConvertCustomAttributes(); +} diff --git a/Migrators/PractiTestExporter/Services/IExportService.cs b/Migrators/PractiTestExporter/Services/IExportService.cs new file mode 100644 index 0000000..0f2365e --- /dev/null +++ b/Migrators/PractiTestExporter/Services/IExportService.cs @@ -0,0 +1,6 @@ +namespace PractiTestExporter.Services; + +public interface IExportService +{ + Task ExportProject(); +} diff --git a/Migrators/PractiTestExporter/Services/ITestCaseService.cs b/Migrators/PractiTestExporter/Services/ITestCaseService.cs new file mode 100644 index 0000000..723cf62 --- /dev/null +++ b/Migrators/PractiTestExporter/Services/ITestCaseService.cs @@ -0,0 +1,8 @@ +using PractiTestExporter.Models; + +namespace PractiTestExporter.Services; + +public interface ITestCaseService +{ + Task ConvertTestCases(Guid sectionId, Dictionary attributeMap); +} diff --git a/Migrators/PractiTestExporter/Services/TestCaseService.cs b/Migrators/PractiTestExporter/Services/TestCaseService.cs new file mode 100644 index 0000000..5eb505b --- /dev/null +++ b/Migrators/PractiTestExporter/Services/TestCaseService.cs @@ -0,0 +1,261 @@ +using Microsoft.Extensions.Logging; +using Models; +using PractiTestExporter.Client; +using PractiTestExporter.Models; +using Constants = PractiTestExporter.Models.Constants; + +namespace PractiTestExporter.Services; + +public class TestCaseService : ITestCaseService +{ + private readonly ILogger _logger; + private readonly IClient _client; + private readonly IAttachmentService _attachmentService; + private readonly Dictionary _sharedSteps; + private readonly Dictionary _testCases; + + public TestCaseService(ILogger logger, IClient client, IAttachmentService attachmentService) + { + _logger = logger; + _client = client; + _attachmentService = attachmentService; + _sharedSteps = new Dictionary(); + _testCases = new Dictionary(); + } + + public async Task ConvertTestCases(Guid sectionId, Dictionary attributeMap) + { + _logger.LogInformation("Converting test cases"); + + var practiTestTestCases = await _client.GetTestCases(); + + _logger.LogDebug("Found {Count} test cases", practiTestTestCases.Count); + + foreach (var practiTestTestCase in practiTestTestCases) + { + if (_sharedSteps.TryGetValue(practiTestTestCase.Id, out var sharedStep)) + { + sharedStep.SectionId = sectionId; + continue; + } + + _testCases.Add( + practiTestTestCase.Id, + await ConvertTestCases( + practiTestTestCase, + sectionId, + attributeMap + ) + ); + } + + _logger.LogInformation("Exported test cases"); + + return new TestCaseData + { + TestCases = _testCases.Values.ToList(), + SharedSteps = _sharedSteps.Values.ToList() + }; + } + + private async Task ConvertTestCases( + PractiTestTestCase practiTestTestCase, + Guid sectionId, + Dictionary attributeMap) + { + var testCaseId = Guid.NewGuid(); + var attributes = ConvertAttributes(practiTestTestCase.Attributes.CustomFields, attributeMap); + var attachments = await _attachmentService.DownloadAttachments( + Constants.TestCaseEntityType, + practiTestTestCase.Id, + testCaseId + ); + var steps = await ConvertSteps(practiTestTestCase.Id, testCaseId, attributeMap); + + steps.ForEach(step => + attachments.AddRange(step.ActionAttachments) + ); + + return new TestCase + { + Id = testCaseId, + Description = practiTestTestCase.Attributes.Description, + State = StateType.NotReady, + Priority = PriorityType.Medium, + Steps = steps, + PreconditionSteps = ConvertPreconditionSteps(practiTestTestCase.Attributes.Preconditions), + PostconditionSteps = new List(), + Duration = 10, + Attributes = attributes, + Tags = practiTestTestCase.Attributes.Tags, + Attachments = attachments, + Iterations = new List(), + Links = new List(), + Name = practiTestTestCase.Attributes.Name, + SectionId = sectionId, + }; + } + + private static List ConvertPreconditionSteps(string preconditions) + { + return string.IsNullOrEmpty(preconditions) + ? new List() + : new List { + new Step + { + Action = preconditions, + Expected = string.Empty, + TestData = string.Empty, + ActionAttachments = new List(), + ExpectedAttachments = new List(), + TestDataAttachments = new List() + } + }; + } + + private async Task ConvertSharedStep(string itemKey, Dictionary attributeMap) + { + if (_sharedSteps.TryGetValue(itemKey, out var step)) + { + return step.Id; + } + + if (_testCases.TryGetValue(itemKey, out var existingTestCase)) + { + var convertedSharedStep = new SharedStep + { + Id = existingTestCase.Id, + Name = existingTestCase.Name, + Description = existingTestCase.Description, + Steps = existingTestCase.Steps, + Attributes = existingTestCase.Attributes, + Attachments = existingTestCase.Attachments, + State = StateType.NotReady, + Priority = PriorityType.Medium, + Tags = existingTestCase.Tags, + Links = existingTestCase.Links, + SectionId = existingTestCase.SectionId + }; + + _testCases.Remove(itemKey); + _sharedSteps.Add(itemKey, convertedSharedStep); + + return convertedSharedStep.Id; + } + + var practiTestTestCase = await _client.GetTestCaseById(itemKey); + var testCaseId = Guid.NewGuid(); + var steps = await ConvertSteps(itemKey, testCaseId, attributeMap); + var attachments = await _attachmentService.DownloadAttachments( + Constants.TestCaseEntityType, + practiTestTestCase.Id, + testCaseId + ); + + steps.ForEach(step => + attachments.AddRange(step.ActionAttachments) + ); + + var sharedStep = new SharedStep + { + Id = testCaseId, + Name = practiTestTestCase.Attributes.Name, + Description = practiTestTestCase.Attributes.Description, + Steps = steps, + Attributes = ConvertAttributes(practiTestTestCase.Attributes.CustomFields, attributeMap), + Attachments = attachments, + State = StateType.NotReady, + Priority = PriorityType.Medium, + Tags = practiTestTestCase.Attributes.Tags, + Links = new List() + }; + + _sharedSteps.Add(itemKey, sharedStep); + + return testCaseId; + } + + private async Task> ConvertSteps( + string practiTestCaseId, + Guid testCaseId, + Dictionary attributeMap) + { + var practiTestSteps = await _client.GetStepsByTestCaseId(practiTestCaseId); + + _logger.LogDebug("Found steps: {@Steps}", practiTestSteps); + + var steps = new List(); + + foreach (var practiTestStep in practiTestSteps) + { + if (practiTestStep.Attributes.TestToCallId != null) + { + var sharedStepId = await ConvertSharedStep(practiTestStep.Attributes.TestToCallId.ToString(), attributeMap); + + steps.Add(new Step + { + SharedStepId = sharedStepId, + Action = string.Empty, + Expected = string.Empty, + TestData = string.Empty, + ActionAttachments = new List(), + ExpectedAttachments = new List(), + TestDataAttachments = new List() + }); + + continue; + } + + steps.Add( + new Step + { + Action = practiTestStep.Attributes.Name, + Expected = practiTestStep.Attributes.ExpectedResults, + TestData = string.Empty, + ActionAttachments = new List(), + ExpectedAttachments = new List(), + TestDataAttachments = new List(), + } + ); + + var attachmentNames = await _attachmentService.DownloadAttachments( + Constants.StepEntityType, + practiTestStep.Id, + testCaseId); + + foreach (var attachmentName in attachmentNames) + { + steps.Last().ActionAttachments.Add(attachmentName); + steps.Last().Action += $"

<<<{attachmentName}>>>

"; + } + } + _logger.LogDebug("Converted steps: {@Steps}", steps); + + return steps; + } + + private List ConvertAttributes( + Dictionary customFields, + Dictionary attributeMap) + { + var attributes = new List(); + + foreach (var customField in customFields) + { + attributes.Add( + new CaseAttribute + { + Id = attributeMap[ConvertCustomFieldKey(customField.Key)], + Value = customField.Value == null ? string.Empty : customField.Value.ToString() + } + ); + } + + return attributes; + } + + private static string ConvertCustomFieldKey(string key) + { + return key.Replace("---f-", string.Empty); + } +} diff --git a/Migrators/PractiTestExporter/practitest.config.json b/Migrators/PractiTestExporter/practitest.config.json new file mode 100644 index 0000000..32aec67 --- /dev/null +++ b/Migrators/PractiTestExporter/practitest.config.json @@ -0,0 +1,8 @@ +{ + "resultPath": "/Users/user01/Documents/importer", + "practiTest": { + "url": "https://prod-api.practitest.app", + "token": "a7b9bea53f1e7a6ef7d3052969b55926680bc13b", + "projectId": "15467" + } +} diff --git a/Migrators/PractiTestExporterTests/AttachmentServiceTests.cs b/Migrators/PractiTestExporterTests/AttachmentServiceTests.cs new file mode 100644 index 0000000..02157d9 --- /dev/null +++ b/Migrators/PractiTestExporterTests/AttachmentServiceTests.cs @@ -0,0 +1,134 @@ +using System.Text; +using JsonWriter; +using Microsoft.Extensions.Logging; +using NSubstitute; +using NSubstitute.ExceptionExtensions; +using PractiTestExporter.Client; +using PractiTestExporter.Models; +using PractiTestExporter.Services; +using Constants = PractiTestExporter.Models.Constants; + +namespace PractiTestExporterTests; + +public class AttachmentServiceTests +{ + private ILogger _logger; + private IClient _client; + private IWriteService _writeService; + private List _attachments; + + [SetUp] + public void Setup() + { + _logger = Substitute.For>(); + _client = Substitute.For(); + _writeService = Substitute.For(); + _attachments = new List + { + new() + { + Id = "123", + Type = "test", + Attributes = new AttachmentAttributes{ Name = "Test.txt" } + } + }; + } + + [Test] + public async Task DownloadAttachment_Success() + { + // Arrange + var bytes = Encoding.UTF8.GetBytes("Test"); + var guid = Guid.NewGuid(); + var entityType = Constants.TestCaseEntityType; + var entityId = "123"; + + _client.GetAttachmentsByEntityId(entityType, entityId) + .Returns(_attachments); + _client.DownloadAttachmentById(Arg.Any()) + .Returns(bytes); + + _writeService.WriteAttachment(guid, bytes, Arg.Any()) + .Returns("Test.txt"); + + var service = new AttachmentService(_logger, _client, _writeService); + + // Act + var result = await service.DownloadAttachments(entityType, entityId, guid); + + // Assert + Assert.That(result, Is.EqualTo(new List { "Test.txt" })); + } + + [Test] + public async Task DownloadAttachment_FailedGetAttachmentsByEntityId() + { + // Arrange + var guid = Guid.NewGuid(); + var entityType = Constants.TestCaseEntityType; + var entityId = "123"; + + _client.GetAttachmentsByEntityId(entityType, entityId) + .Throws(new Exception("Failed to get attachment")); + + var service = new AttachmentService(_logger, _client, _writeService); + + // Act + Assert.ThrowsAsync(async () => + await service.DownloadAttachments(entityType, entityId, guid)); + + // Assert + await _client.DidNotReceive() + .DownloadAttachmentById(Arg.Any()); + await _writeService.DidNotReceive() + .WriteAttachment(Arg.Any(), Arg.Any(), Arg.Any()); + } + + [Test] + public async Task DownloadAttachment_FailedDownloadAttachment() + { + // Arrange + var guid = Guid.NewGuid(); + var entityType = Constants.TestCaseEntityType; + var entityId = "123"; + + _client.GetAttachmentsByEntityId(entityType, entityId) + .Returns(_attachments); + _client.DownloadAttachmentById(Arg.Any()) + .Throws(new Exception("Failed to download attachment")); + + var service = new AttachmentService(_logger, _client, _writeService); + + // Act + Assert.ThrowsAsync(async () => + await service.DownloadAttachments(entityType, entityId, guid)); + + // Assert + await _writeService.DidNotReceive() + .WriteAttachment(Arg.Any(), Arg.Any(), Arg.Any()); + } + + [Test] + public async Task DownloadAttachment_FailedWriteAttachment() + { + // Arrange + var bytes = Encoding.UTF8.GetBytes("Test"); + var guid = Guid.NewGuid(); + var entityType = Constants.TestCaseEntityType; + var entityId = "123"; + + _client.GetAttachmentsByEntityId(entityType, entityId) + .Returns(_attachments); + _client.DownloadAttachmentById(Arg.Any()) + .Returns(bytes); + + _writeService.WriteAttachment(guid, bytes, Arg.Any()) + .Throws(new Exception("Failed to write attachment")); + + var service = new AttachmentService(_logger, _client, _writeService); + + // Act + Assert.ThrowsAsync(async () => + await service.DownloadAttachments(entityType, entityId, guid)); + } +} diff --git a/Migrators/PractiTestExporterTests/AttributeServiceTests.cs b/Migrators/PractiTestExporterTests/AttributeServiceTests.cs new file mode 100644 index 0000000..1e562bc --- /dev/null +++ b/Migrators/PractiTestExporterTests/AttributeServiceTests.cs @@ -0,0 +1,145 @@ +using PractiTestExporter.Client; +using PractiTestExporter.Models; +using PractiTestExporter.Services; +using Microsoft.Extensions.Logging; +using NSubstitute; +using NSubstitute.ExceptionExtensions; +using Models; + +namespace PractiTestExporterTests; + +public class AttributeServiceTests +{ + private ILogger _logger; + private IClient _client; + + private List _customFields; + private ListPractiTestCustomField _listCustomField; + + [SetUp] + public void Setup() + { + _logger = Substitute.For>(); + _client = Substitute.For(); + + _customFields = new List + { + new() + { + Id = "123", + Attributes = new CustomFieldAttributes + { + Name = "test list", + FieldFormat = "list" + } + }, + new() + { + Id = "321", + Attributes = new CustomFieldAttributes + { + Name = "test text", + FieldFormat = "text" + } + }, + new() + { + Id = "111", + Attributes = new CustomFieldAttributes + { + Name = "test date", + FieldFormat = "date" + } + }, + new() + { + Id = "333", + Attributes = new CustomFieldAttributes + { + Name = "test any", + FieldFormat = "any" + } + } + }; + + _listCustomField = new ListPractiTestCustomField + { + Id = "123", + Attributes = new ListCustomFieldAttributes + { + Name = "test", + FieldFormat = "list", + PossibleValues = new List { "value1", "value2", "value3" } + } + }; + } + + [Test] + public async Task GetCustomAttributes_FailedGetCustomFieldNames() + { + // Arrange + _client.GetCustomFields() + .ThrowsAsync(new Exception("Failed to get custom fields")); + + var service = new AttributeService(_logger, _client); + + // Act + Assert.ThrowsAsync(async () => + await service.ConvertCustomAttributes()); + + // Assert + await _client.DidNotReceive() + .GetListCustomFieldById(Arg.Any()); + } + + [Test] + public async Task GetCustomAttributes_FailedGetCustomFieldValues() + { + // Arrange + _client.GetCustomFields() + .Returns(_customFields); + + _client.GetListCustomFieldById(Arg.Any()) + .ThrowsAsync(new Exception("Failed to get custom field values")); + + var service = new AttributeService(_logger, _client); + + // Act + Assert.ThrowsAsync(async () => + await service.ConvertCustomAttributes()); + } + + [Test] + public async Task GetCustomAttributes_Success() + { + // Arrange + _client.GetCustomFields() + .Returns(_customFields); + + _client.GetListCustomFieldById(Arg.Any()) + .Returns(_listCustomField); + + var service = new AttributeService(_logger, _client); + + // Act + var attributes = await service.ConvertCustomAttributes(); + + // Assert + Assert.That(attributes.Attributes, Has.Count.EqualTo(4)); + Assert.That(attributes.Attributes[0].Name, Is.EqualTo("test list")); + Assert.That(attributes.Attributes[0].Type, Is.EqualTo(AttributeType.Options)); + Assert.That(attributes.Attributes[0].Options, Has.Count.EqualTo(3)); + Assert.That(attributes.Attributes[0].Options[0], Is.EqualTo("value1")); + Assert.That(attributes.Attributes[0].Options[1], Is.EqualTo("value2")); + Assert.That(attributes.Attributes[0].Options[2], Is.EqualTo("value3")); + Assert.That(attributes.Attributes[1].Name, Is.EqualTo("test text")); + Assert.That(attributes.Attributes[1].Type, Is.EqualTo(AttributeType.String)); + Assert.That(attributes.Attributes[1].Options, Has.Count.EqualTo(0)); + Assert.That(attributes.Attributes[2].Name, Is.EqualTo("test date")); + Assert.That(attributes.Attributes[2].Type, Is.EqualTo(AttributeType.Datetime)); + Assert.That(attributes.Attributes[2].Options, Has.Count.EqualTo(0)); + Assert.That(attributes.Attributes[3].Name, Is.EqualTo("test any")); + Assert.That(attributes.Attributes[3].Type, Is.EqualTo(AttributeType.String)); + Assert.That(attributes.Attributes[3].Options, Has.Count.EqualTo(0)); + } +} diff --git a/Migrators/PractiTestExporterTests/ExportServiceTests.cs b/Migrators/PractiTestExporterTests/ExportServiceTests.cs new file mode 100644 index 0000000..ac73af6 --- /dev/null +++ b/Migrators/PractiTestExporterTests/ExportServiceTests.cs @@ -0,0 +1,279 @@ +using JsonWriter; +using Microsoft.Extensions.Logging; +using Models; +using NSubstitute; +using NSubstitute.ExceptionExtensions; +using NUnit.Framework; +using PractiTestExporter.Client; +using PractiTestExporter.Models; +using PractiTestExporter.Services; +using Attribute = Models.Attribute; +using Step = Models.Step; +using TestCaseData = PractiTestExporter.Models.TestCaseData; + +namespace PractiTestExporterTests; + +public class ExportServiceTests +{ + private ILogger _logger; + private IClient _client; + private ITestCaseService _testCaseService; + private IWriteService _writeService; + private IAttributeService _attributeService; + + private PractiTestProject _project; + private AttributeData _attributeData; + private TestCaseData _testCaseData; + + [SetUp] + public void Setup() + { + _logger = Substitute.For>(); + _client = Substitute.For(); + _testCaseService = Substitute.For(); + _writeService = Substitute.For(); + _attributeService = Substitute.For(); + + _project = new PractiTestProject + { + Data = new ProjectData + { + Id = "123", + Attributes = new ProjectAttributes + { + Name = "My project" + } + }, + }; + + _attributeData = new AttributeData + { + Attributes = new List(), + AttributeMap = new Dictionary() + }; + + _testCaseData = new TestCaseData + { + SharedSteps = new List + { + new() + { + Id = Guid.NewGuid(), + Name = "Shared step 1" + } + }, + TestCases = new List + { + new() + { + Id = Guid.NewGuid(), + Name = "Test case 1" + } + } + }; + } + + [Test] + public async Task ExportProject_FailedGetProject() + { + // Arrange + _client.GetProject() + .Throws(new Exception("Failed to get project")); + + var exportService = new ExportService(_logger, _client, _writeService, _testCaseService, _attributeService); + + // Act + Assert.ThrowsAsync(async () => await exportService.ExportProject()); + + // Assert + await _testCaseService.DidNotReceive() + .ConvertTestCases(Arg.Any(), Arg.Any>()); + + await _writeService.DidNotReceive() + .WriteSharedStep(Arg.Any()); + + await _writeService.DidNotReceive() + .WriteTestCase(Arg.Any()); + + await _writeService.DidNotReceive() + .WriteMainJson(Arg.Any()); + } + + [Test] + public async Task ExportProject_FailedConvertCustomAttributes() + { + // Arrange + _client.GetProject() + .Returns(_project); + + _attributeService.ConvertCustomAttributes() + .Throws(new Exception("Failed to convert custom attributes")); + + var exportService = new ExportService(_logger, _client, _writeService, _testCaseService, _attributeService); + + // Act + Assert.ThrowsAsync(async () => await exportService.ExportProject()); + + // Assert + await _testCaseService.DidNotReceive() + .ConvertTestCases(Arg.Any(), Arg.Any>()); + + await _writeService.DidNotReceive() + .WriteSharedStep(Arg.Any()); + + await _writeService.DidNotReceive() + .WriteTestCase(Arg.Any()); + + await _writeService.DidNotReceive() + .WriteMainJson(Arg.Any()); + } + + [Test] + public async Task ExportProject_FailedConvertTestCases() + { + // Arrange + _client.GetProject() + .Returns(_project); + + _attributeService.ConvertCustomAttributes() + .Returns(_attributeData); + + _testCaseService.ConvertTestCases(Arg.Any(), _attributeData.AttributeMap) + .Throws(new Exception("Failed to convert test cases")); + + var exportService = new ExportService(_logger, _client, _writeService, _testCaseService, _attributeService); + + // Act + Assert.ThrowsAsync(async () => await exportService.ExportProject()); + + // Assert + await _writeService.DidNotReceive() + .WriteSharedStep(Arg.Any()); + + await _writeService.DidNotReceive() + .WriteTestCase(Arg.Any()); + + await _writeService.DidNotReceive() + .WriteMainJson(Arg.Any()); + } + + [Test] + public async Task ExportProject_FailedWriteSharedStep() + { + // Arrange + _client.GetProject() + .Returns(_project); + + _attributeService.ConvertCustomAttributes() + .Returns(_attributeData); + + _testCaseService.ConvertTestCases(Arg.Any(), Arg.Any>()) + .Returns(_testCaseData); + + _writeService.WriteSharedStep(_testCaseData.SharedSteps[0]) + .Throws(new Exception("Failed to write shared step")); + + var exportService = new ExportService(_logger, _client, _writeService, _testCaseService, _attributeService); + + // Act + Assert.ThrowsAsync(async () => await exportService.ExportProject()); + + // Assert + + await _writeService.DidNotReceive() + .WriteTestCase(Arg.Any()); + + await _writeService.DidNotReceive() + .WriteMainJson(Arg.Any()); + } + + [Test] + public async Task ExportProject_FailedWriteTestCase() + { + // Arrange + _client.GetProject() + .Returns(_project); + + _attributeService.ConvertCustomAttributes() + .Returns(_attributeData); + + _testCaseService.ConvertTestCases(Arg.Any(), Arg.Any>()) + .Returns(_testCaseData); + + _writeService.WriteTestCase(_testCaseData.TestCases[0]) + .Throws(new Exception("Failed to write test case")); + + var exportService = new ExportService(_logger, _client, _writeService, _testCaseService, _attributeService); + + // Act + Assert.ThrowsAsync(async () => await exportService.ExportProject()); + + // Assert + await _writeService.Received() + .WriteSharedStep(_testCaseData.SharedSteps[0]); + + await _writeService.DidNotReceive() + .WriteMainJson(Arg.Any()); + } + + [Test] + public async Task ExportProject_FailedWriteMainJson() + { + // Arrange + _client.GetProject() + .Returns(_project); + + _attributeService.ConvertCustomAttributes() + .Returns(_attributeData); + + _testCaseService.ConvertTestCases(Arg.Any(), Arg.Any>()) + .Returns(_testCaseData); + + _writeService.WriteMainJson(Arg.Any()) + .Throws(new Exception("Failed to write test case")); + + var exportService = new ExportService(_logger, _client, _writeService, _testCaseService, _attributeService); + + // Act + Assert.ThrowsAsync(async () => await exportService.ExportProject()); + + // Assert + await _writeService.Received() + .WriteSharedStep(_testCaseData.SharedSteps[0]); + + await _writeService.Received() + .WriteTestCase(_testCaseData.TestCases[0]); + } + + [Test] + public async Task ExportProject_Success() + { + // Arrange + _client.GetProject() + .Returns(_project); + + _attributeService.ConvertCustomAttributes() + .Returns(_attributeData); + + _testCaseService.ConvertTestCases(Arg.Any(), Arg.Any>()) + .Returns(_testCaseData); + + _writeService.WriteMainJson(Arg.Any()) + .Throws(new Exception("Failed to write test case")); + + var exportService = new ExportService(_logger, _client, _writeService, _testCaseService, _attributeService); + + // Act + Assert.ThrowsAsync(async () => await exportService.ExportProject()); + + // Assert + await _writeService.Received() + .WriteSharedStep(_testCaseData.SharedSteps[0]); + + await _writeService.Received() + .WriteTestCase(_testCaseData.TestCases[0]); + + await _writeService.Received() + .WriteMainJson(Arg.Any()); + } +} diff --git a/Migrators/PractiTestExporterTests/GlobalUsings.cs b/Migrators/PractiTestExporterTests/GlobalUsings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/Migrators/PractiTestExporterTests/GlobalUsings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file diff --git a/Migrators/PractiTestExporterTests/PractiTestExporterTests.csproj b/Migrators/PractiTestExporterTests/PractiTestExporterTests.csproj new file mode 100644 index 0000000..a216e89 --- /dev/null +++ b/Migrators/PractiTestExporterTests/PractiTestExporterTests.csproj @@ -0,0 +1,32 @@ + + + + net7.0 + enable + enable + + false + true + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/Migrators/PractiTestExporterTests/TestCaseServiceTests.cs b/Migrators/PractiTestExporterTests/TestCaseServiceTests.cs new file mode 100644 index 0000000..02a660c --- /dev/null +++ b/Migrators/PractiTestExporterTests/TestCaseServiceTests.cs @@ -0,0 +1,386 @@ +using Microsoft.Extensions.Logging; +using NSubstitute; +using NSubstitute.ExceptionExtensions; +using PractiTestExporter.Client; +using PractiTestExporter.Models; +using PractiTestExporter.Services; + +namespace PractiTestExporterTests; + +public class TestCaseServiceTests +{ + private ILogger _logger; + private IClient _client; + private IAttachmentService _attachmentService; + private Dictionary _attributeMap; + private List _tests; + private List _steps; + private List _sharedSteps; + private List _sharedStepSteps; + private List _attachments; + + [SetUp] + public void Setup() + { + _logger = Substitute.For>(); + _client = Substitute.For(); + _attachmentService = Substitute.For(); + + _attributeMap = new Dictionary + { + { "222", new Guid() }, + { "111", new Guid() } + }; + + _sharedSteps = new List + { + new() + { + Id = "777", + Attributes = new TestCaseAttributes + { + Name = "shared test 1", + Preconditions = "precon 1", + Description = "desc 1", + Tags = new List { "tag1", "tag2", "tag3" }, + CustomFields = new Dictionary + { + { "---f-222", "value1" }, + { "---f-111", "value2" } + } + } + }, + new() + { + Id = "888", + Attributes = new TestCaseAttributes + { + Name = "shared test 2", + Preconditions = "precon 2", + Description = "desc 2", + Tags = new List { "tag11", "tag21", "tag31" }, + CustomFields = new Dictionary + { + { "---f-222", "value1" }, + { "---f-111", "value2" } + } + } + }, + }; + + _tests = new List + { + _sharedSteps[0], + new() + { + Id = "123", + Attributes = new TestCaseAttributes + { + Name = "test2", + Preconditions = "precon2", + Description = "desc2", + Tags = new List { "tag3", "tag2", "tag1" }, + CustomFields = new Dictionary + { + { "---f-222", "value1" }, + { "---f-111", "value2" } + } + } + }, + _sharedSteps[1], + }; + + _steps = new List + { + new() + { + Id = "1", + Attributes = new StepAttributes + { + Name = "step1", + Description = "desc", + ExpectedResults = "expected", + TestToCallId = null + } + }, + new() + { + Id = "1", + Attributes = new StepAttributes + { + TestToCallId = 777 + } + }, + new() + { + Id = "1", + Attributes = new StepAttributes + { + TestToCallId = 888 + } + }, + new() + { + Id = "1", + Attributes = new StepAttributes + { + TestToCallId = 777 + } + }, + }; + + _sharedStepSteps = new List + { + new() + { + Id = "2", + Attributes = new StepAttributes + { + Name = "step1", + Description = "desc1", + ExpectedResults = "expected1", + TestToCallId = null + } + }, + new() + { + Id = "2", + Attributes = new StepAttributes + { + Name = "step2", + Description = "desc2", + ExpectedResults = "expected2", + TestToCallId = null + } + } + }; + + _attachments = new List() { "Test.txt" }; + } + + [Test] + public async Task ConvertTestCases_FailedGetTestCases() + { + // Arrange + var sectionId = new Guid(); + + _client.GetTestCases() + .Throws(new Exception("Failed to get test")); + + var testCaseService = new TestCaseService(_logger, _client, _attachmentService); + + // Act + Assert.ThrowsAsync(() => testCaseService.ConvertTestCases(sectionId, _attributeMap)); + + // Assert + await _client.DidNotReceive() + .GetTestCaseById(Arg.Any()); + + await _attachmentService.DidNotReceive() + .DownloadAttachments(Arg.Any(), Arg.Any(), Arg.Any()); + } + + [Test] + public async Task ConvertTestCases_FailedStepsByTestCaseId() + { + // Arrange + var sectionId = new Guid(); + + _client.GetTestCases() + .Returns(_tests); + + _attachmentService.DownloadAttachments(Arg.Any(), Arg.Any(), Arg.Any()) + .Returns(_attachments); + + _client.GetStepsByTestCaseId(Arg.Any()) + .Throws(new Exception("Failed to get steps")); + + var testCaseService = new TestCaseService(_logger, _client, _attachmentService); + + // Act + Assert.ThrowsAsync(() => testCaseService.ConvertTestCases(sectionId, _attributeMap)); + } + + [Test] + public async Task ConvertTestCases_FailedGetTestCaseById() + { + // Arrange + var sectionId = new Guid(); + + _client.GetTestCases() + .Returns(_tests); + + _client.GetStepsByTestCaseId(_tests[0].Id) + .Returns(_steps); + + _attachmentService.DownloadAttachments(Arg.Any(), Arg.Any(), Arg.Any()) + .Returns(_attachments); + + _client.GetTestCaseById(Arg.Any()) + .Throws(new Exception("Failed to get test case")); + + var testCaseService = new TestCaseService(_logger, _client, _attachmentService); + + // Act + Assert.ThrowsAsync(() => testCaseService.ConvertTestCases(sectionId, _attributeMap)); + } + + [Test] + public async Task ConvertTestCases_FailedDownloadAttachment() + { + // Arrange + var sectionId = new Guid(); + + _client.GetTestCases() + .Returns(_tests); + + _client.GetStepsByTestCaseId(_tests[0].Id) + .Returns(_steps); + + _client.GetTestCaseById(Arg.Any()) + .Returns(_sharedSteps[0]); + + _client.GetStepsByTestCaseId(_sharedSteps[0].Id) + .Returns(_sharedStepSteps); + + _attachmentService.DownloadAttachments(Arg.Any(), Arg.Any(), Arg.Any()) + .Throws(new Exception("Failed to download attachment")); + + var testCaseService = new TestCaseService(_logger, _client, _attachmentService); + + // Act + Assert.ThrowsAsync(() => testCaseService.ConvertTestCases(sectionId, _attributeMap)); + } + + [Test] + public async Task ConvertTestCases_Success_WithSharedStep() + { + // Arrange + var sectionId = new Guid(); + + _client.GetTestCases() + .Returns(_tests); + + _client.GetStepsByTestCaseId(_tests[1].Id) + .Returns(_steps); + + _client.GetTestCaseById(_sharedSteps[0].Id) + .Returns(_sharedSteps[0]); + + _client.GetTestCaseById(_sharedSteps[1].Id) + .Returns(_sharedSteps[1]); + + _client.GetStepsByTestCaseId(_sharedSteps[0].Id) + .Returns(_sharedStepSteps); + + _client.GetStepsByTestCaseId(_sharedSteps[1].Id) + .Returns(_sharedStepSteps); + + _attachmentService.DownloadAttachments(Arg.Any(), _tests[1].Id, Arg.Any()) + .Returns(_attachments); + + _attachmentService.DownloadAttachments(Arg.Any(), _steps[0].Id, Arg.Any()) + .Returns(new List()); + + _attachmentService.DownloadAttachments(Arg.Any(), _sharedSteps[0].Id, Arg.Any()) + .Returns(new List()); + + _attachmentService.DownloadAttachments(Arg.Any(), _sharedSteps[1].Id, Arg.Any()) + .Returns(new List()); + + _attachmentService.DownloadAttachments(Arg.Any(), _sharedStepSteps[0].Id, Arg.Any()) + .Returns(_attachments); + + var testCaseService = new TestCaseService(_logger, _client, _attachmentService); + + // Act + var result = await testCaseService.ConvertTestCases(sectionId, _attributeMap); + + // Assert + Assert.That(result.TestCases, Has.Count.EqualTo(1)); + Assert.That(result.TestCases[0].Name, Is.EqualTo(_tests[1].Attributes.Name)); + Assert.That(result.TestCases[0].Description, Is.EqualTo(_tests[1].Attributes.Description)); + Assert.That(result.TestCases[0].PreconditionSteps, Has.Count.EqualTo(1)); + Assert.That(result.TestCases[0].PreconditionSteps[0].Action, Is.EqualTo(_tests[1].Attributes.Preconditions)); + Assert.That(result.TestCases[0].Steps, Has.Count.EqualTo(4)); + Assert.That(result.TestCases[0].Steps[0].Action, Is.EqualTo(_steps[0].Attributes.Name)); + Assert.That(result.TestCases[0].Steps[0].Expected, Is.EqualTo(_steps[0].Attributes.ExpectedResults)); + Assert.That(result.TestCases[0].Steps[0].TestData, Is.EqualTo(string.Empty)); + Assert.That(result.TestCases[0].Steps[0].ActionAttachments, Has.Count.EqualTo(0)); + Assert.That(result.TestCases[0].Steps[0].ExpectedAttachments, Has.Count.EqualTo(0)); + Assert.That(result.TestCases[0].Steps[0].TestDataAttachments, Has.Count.EqualTo(0)); + Assert.That(result.TestCases[0].Steps[1].Action, Is.EqualTo(string.Empty)); + Assert.That(result.TestCases[0].Steps[1].Expected, Is.EqualTo(string.Empty)); + Assert.That(result.TestCases[0].Steps[1].TestData, Is.EqualTo(string.Empty)); + Assert.That(result.TestCases[0].Steps[1].ActionAttachments, Has.Count.EqualTo(0)); + Assert.That(result.TestCases[0].Steps[1].ExpectedAttachments, Has.Count.EqualTo(0)); + Assert.That(result.TestCases[0].Steps[1].TestDataAttachments, Has.Count.EqualTo(0)); + Assert.That(result.TestCases[0].Steps[2].Action, Is.EqualTo(string.Empty)); + Assert.That(result.TestCases[0].Steps[2].Expected, Is.EqualTo(string.Empty)); + Assert.That(result.TestCases[0].Steps[2].TestData, Is.EqualTo(string.Empty)); + Assert.That(result.TestCases[0].Steps[2].ActionAttachments, Has.Count.EqualTo(0)); + Assert.That(result.TestCases[0].Steps[2].ExpectedAttachments, Has.Count.EqualTo(0)); + Assert.That(result.TestCases[0].Steps[2].TestDataAttachments, Has.Count.EqualTo(0)); + Assert.That(result.TestCases[0].Steps[3].Action, Is.EqualTo(string.Empty)); + Assert.That(result.TestCases[0].Steps[3].Expected, Is.EqualTo(string.Empty)); + Assert.That(result.TestCases[0].Steps[3].TestData, Is.EqualTo(string.Empty)); + Assert.That(result.TestCases[0].Steps[3].ActionAttachments, Has.Count.EqualTo(0)); + Assert.That(result.TestCases[0].Steps[3].ExpectedAttachments, Has.Count.EqualTo(0)); + Assert.That(result.TestCases[0].Steps[3].TestDataAttachments, Has.Count.EqualTo(0)); + Assert.That(result.TestCases[0].Tags, Has.Count.EqualTo(3)); + Assert.That(result.TestCases[0].Attributes, Has.Count.EqualTo(2)); + Assert.That(result.TestCases[0].Attributes[0].Id, Is.EqualTo(_attributeMap["222"])); + Assert.That(result.TestCases[0].Attributes[0].Value, Is.EqualTo(_tests[0].Attributes.CustomFields["---f-222"])); + Assert.That(result.TestCases[0].Attributes[1].Id, Is.EqualTo(_attributeMap["111"])); + Assert.That(result.TestCases[0].Attributes[1].Value, Is.EqualTo(_tests[0].Attributes.CustomFields["---f-111"])); + Assert.That(result.TestCases[0].Tags[0], Is.EqualTo("tag3")); + Assert.That(result.TestCases[0].Tags[1], Is.EqualTo("tag2")); + Assert.That(result.TestCases[0].Tags[2], Is.EqualTo("tag1")); + Assert.That(result.TestCases[0].Links, Has.Count.EqualTo(0)); + Assert.That(result.TestCases[0].Attachments, Has.Count.EqualTo(1)); + Assert.That(result.TestCases[0].Attachments[0], Is.EqualTo("Test.txt")); + Assert.That(result.SharedSteps, Has.Count.EqualTo(2)); + Assert.That(result.SharedSteps[0].Name, Is.EqualTo(_sharedSteps[0].Attributes.Name)); + Assert.That(result.SharedSteps[0].Description, Is.EqualTo(_sharedSteps[0].Attributes.Description)); + Assert.That(result.SharedSteps[0].Steps, Has.Count.EqualTo(2)); + Assert.That(result.SharedSteps[0].Steps[0].Action, Is.EqualTo(_sharedStepSteps[0].Attributes.Name + $"

<<<{_attachments[0]}>>>

")); + Assert.That(result.SharedSteps[0].Steps[0].Expected, Is.EqualTo(_sharedStepSteps[0].Attributes.ExpectedResults)); + Assert.That(result.SharedSteps[0].Steps[0].TestData, Is.EqualTo(string.Empty)); + Assert.That(result.SharedSteps[0].Steps[0].ActionAttachments, Has.Count.EqualTo(1)); + Assert.That(result.SharedSteps[0].Steps[0].ExpectedAttachments, Has.Count.EqualTo(0)); + Assert.That(result.SharedSteps[0].Steps[0].TestDataAttachments, Has.Count.EqualTo(0)); + Assert.That(result.SharedSteps[0].Steps[1].Action, Is.EqualTo(_sharedStepSteps[1].Attributes.Name + $"

<<<{_attachments[0]}>>>

")); + Assert.That(result.SharedSteps[0].Steps[1].Expected, Is.EqualTo(_sharedStepSteps[1].Attributes.ExpectedResults)); + Assert.That(result.SharedSteps[0].Steps[1].TestData, Is.EqualTo(string.Empty)); + Assert.That(result.SharedSteps[0].Steps[1].ActionAttachments, Has.Count.EqualTo(1)); + Assert.That(result.SharedSteps[0].Steps[1].ExpectedAttachments, Has.Count.EqualTo(0)); + Assert.That(result.SharedSteps[0].Steps[1].TestDataAttachments, Has.Count.EqualTo(0)); + Assert.That(result.SharedSteps[0].Tags, Has.Count.EqualTo(3)); + Assert.That(result.SharedSteps[0].Tags[0], Is.EqualTo("tag1")); + Assert.That(result.SharedSteps[0].Tags[1], Is.EqualTo("tag2")); + Assert.That(result.SharedSteps[0].Tags[2], Is.EqualTo("tag3")); + Assert.That(result.SharedSteps[0].Links, Has.Count.EqualTo(0)); + Assert.That(result.SharedSteps[0].Attachments, Has.Count.EqualTo(2)); + Assert.That(result.SharedSteps[1].Name, Is.EqualTo(_sharedSteps[1].Attributes.Name)); + Assert.That(result.SharedSteps[1].Description, Is.EqualTo(_sharedSteps[1].Attributes.Description)); + Assert.That(result.SharedSteps[1].Steps, Has.Count.EqualTo(2)); + Assert.That(result.SharedSteps[1].Steps[0].Action, Is.EqualTo(_sharedStepSteps[0].Attributes.Name + $"

<<<{_attachments[0]}>>>

")); + Assert.That(result.SharedSteps[1].Steps[0].Expected, Is.EqualTo(_sharedStepSteps[0].Attributes.ExpectedResults)); + Assert.That(result.SharedSteps[1].Steps[0].TestData, Is.EqualTo(string.Empty)); + Assert.That(result.SharedSteps[1].Steps[0].ActionAttachments, Has.Count.EqualTo(1)); + Assert.That(result.SharedSteps[1].Steps[0].ExpectedAttachments, Has.Count.EqualTo(0)); + Assert.That(result.SharedSteps[1].Steps[0].TestDataAttachments, Has.Count.EqualTo(0)); + Assert.That(result.SharedSteps[1].Steps[1].Action, Is.EqualTo(_sharedStepSteps[1].Attributes.Name + $"

<<<{_attachments[0]}>>>

")); + Assert.That(result.SharedSteps[1].Steps[1].Expected, Is.EqualTo(_sharedStepSteps[1].Attributes.ExpectedResults)); + Assert.That(result.SharedSteps[1].Steps[1].TestData, Is.EqualTo(string.Empty)); + Assert.That(result.SharedSteps[1].Steps[1].ActionAttachments, Has.Count.EqualTo(1)); + Assert.That(result.SharedSteps[1].Steps[1].ExpectedAttachments, Has.Count.EqualTo(0)); + Assert.That(result.SharedSteps[1].Steps[1].TestDataAttachments, Has.Count.EqualTo(0)); + Assert.That(result.SharedSteps[1].Tags, Has.Count.EqualTo(3)); + Assert.That(result.SharedSteps[1].Tags[0], Is.EqualTo("tag11")); + Assert.That(result.SharedSteps[1].Tags[1], Is.EqualTo("tag21")); + Assert.That(result.SharedSteps[1].Tags[2], Is.EqualTo("tag31")); + Assert.That(result.SharedSteps[1].Links, Has.Count.EqualTo(0)); + Assert.That(result.SharedSteps[1].Attachments, Has.Count.EqualTo(2)); + } +} diff --git a/Migrators/TestLinkExporter/Readme.md b/Migrators/TestLinkExporter/Readme.md index 20ea579..ef32c79 100644 --- a/Migrators/TestLinkExporter/Readme.md +++ b/Migrators/TestLinkExporter/Readme.md @@ -24,9 +24,9 @@ You can download the latest version of the TestLinkExporter from the [releases]( Where: - resultPath - path to the folder where the results will be saved -- testlink.url - TestLink API url -- testlink.token - token for access to the TestLink -- testlink.projectName - name of the project in the TestLink +- testLink.url - TestLink API url +- testLink.token - token for access to the TestLink +- testLink.projectName - name of the project in the TestLink 1. Run the exporter with the following command: From f5d3e8444e247376dfd64054904fd0ca79d93804 Mon Sep 17 00:00:00 2001 From: "pavel.butuzov" Date: Tue, 14 Nov 2023 09:46:20 +0300 Subject: [PATCH 2/4] Updated documentation. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c153e1f..a03e340 100644 --- a/README.md +++ b/README.md @@ -11,5 +11,6 @@ We support the following systems: - [XRay](https://github.com/testit-tms/migrators/tree/main/Migrators/XRayExporter/Readme.md) - [TestCollab](https://github.com/testit-tms/migrators/tree/main/Migrators/TestCollabExporter/Readme.md) - [TestLink](https://github.com/testit-tms/migrators/tree/main/Migrators/TestLinkExporter/Readme.md) +- [PractiTest](https://github.com/testit-tms/migrators/tree/main/Migrators/PractiTestExporter/Readme.md) We are constantly working on new migrators. If you need a migrator for a system that is not listed here, please contact us at [support@yoonion.ru](mailto:support@yoonion.ru). From c4bb309f538f146177ee0c00ff599b0e248b6888 Mon Sep 17 00:00:00 2001 From: "pavel.butuzov" Date: Thu, 16 Nov 2023 10:37:51 +0300 Subject: [PATCH 3/4] Added changes from code review. --- .../PractiTestExporter/Models/Constants.cs | 1 + Migrators/PractiTestExporter/Readme.md | 2 +- .../Services/TestCaseService.cs | 2 +- .../AttachmentServiceTests.cs | 31 +++++++++---------- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/Migrators/PractiTestExporter/Models/Constants.cs b/Migrators/PractiTestExporter/Models/Constants.cs index 7ee0b12..0d369b5 100644 --- a/Migrators/PractiTestExporter/Models/Constants.cs +++ b/Migrators/PractiTestExporter/Models/Constants.cs @@ -7,4 +7,5 @@ public class Constants public const string DateCustomFieldType = "date"; public const string TestCaseEntityType = "test"; public const string StepEntityType = "step"; + public const int Duration = 10000; } diff --git a/Migrators/PractiTestExporter/Readme.md b/Migrators/PractiTestExporter/Readme.md index 6099451..40cab07 100644 --- a/Migrators/PractiTestExporter/Readme.md +++ b/Migrators/PractiTestExporter/Readme.md @@ -28,7 +28,7 @@ Where: - practiTest.token - token for access to the PractiTest - practiTest.projectName - name of the project in the PractiTest -1. Run the exporter with the following command: +2. Run the exporter with the following command: ```bash .\PractiTestExporter diff --git a/Migrators/PractiTestExporter/Services/TestCaseService.cs b/Migrators/PractiTestExporter/Services/TestCaseService.cs index 5eb505b..c010f9e 100644 --- a/Migrators/PractiTestExporter/Services/TestCaseService.cs +++ b/Migrators/PractiTestExporter/Services/TestCaseService.cs @@ -85,7 +85,7 @@ private async Task ConvertTestCases( Steps = steps, PreconditionSteps = ConvertPreconditionSteps(practiTestTestCase.Attributes.Preconditions), PostconditionSteps = new List(), - Duration = 10, + Duration = Constants.Duration, Attributes = attributes, Tags = practiTestTestCase.Attributes.Tags, Attachments = attachments, diff --git a/Migrators/PractiTestExporterTests/AttachmentServiceTests.cs b/Migrators/PractiTestExporterTests/AttachmentServiceTests.cs index 02157d9..f2298bd 100644 --- a/Migrators/PractiTestExporterTests/AttachmentServiceTests.cs +++ b/Migrators/PractiTestExporterTests/AttachmentServiceTests.cs @@ -16,6 +16,7 @@ public class AttachmentServiceTests private IClient _client; private IWriteService _writeService; private List _attachments; + private const string _entityId = "111"; [SetUp] public void Setup() @@ -41,20 +42,19 @@ public async Task DownloadAttachment_Success() var bytes = Encoding.UTF8.GetBytes("Test"); var guid = Guid.NewGuid(); var entityType = Constants.TestCaseEntityType; - var entityId = "123"; - _client.GetAttachmentsByEntityId(entityType, entityId) + _client.GetAttachmentsByEntityId(entityType, _entityId) .Returns(_attachments); - _client.DownloadAttachmentById(Arg.Any()) + _client.DownloadAttachmentById(_attachments[0].Id) .Returns(bytes); - _writeService.WriteAttachment(guid, bytes, Arg.Any()) + _writeService.WriteAttachment(guid, bytes, _attachments[0].Attributes.Name) .Returns("Test.txt"); var service = new AttachmentService(_logger, _client, _writeService); // Act - var result = await service.DownloadAttachments(entityType, entityId, guid); + var result = await service.DownloadAttachments(entityType, _entityId, guid); // Assert Assert.That(result, Is.EqualTo(new List { "Test.txt" })); @@ -66,16 +66,15 @@ public async Task DownloadAttachment_FailedGetAttachmentsByEntityId() // Arrange var guid = Guid.NewGuid(); var entityType = Constants.TestCaseEntityType; - var entityId = "123"; - _client.GetAttachmentsByEntityId(entityType, entityId) + _client.GetAttachmentsByEntityId(entityType, _entityId) .Throws(new Exception("Failed to get attachment")); var service = new AttachmentService(_logger, _client, _writeService); // Act Assert.ThrowsAsync(async () => - await service.DownloadAttachments(entityType, entityId, guid)); + await service.DownloadAttachments(entityType, _entityId, guid)); // Assert await _client.DidNotReceive() @@ -90,18 +89,17 @@ public async Task DownloadAttachment_FailedDownloadAttachment() // Arrange var guid = Guid.NewGuid(); var entityType = Constants.TestCaseEntityType; - var entityId = "123"; - _client.GetAttachmentsByEntityId(entityType, entityId) + _client.GetAttachmentsByEntityId(entityType, _entityId) .Returns(_attachments); - _client.DownloadAttachmentById(Arg.Any()) + _client.DownloadAttachmentById(_attachments[0].Id) .Throws(new Exception("Failed to download attachment")); var service = new AttachmentService(_logger, _client, _writeService); // Act Assert.ThrowsAsync(async () => - await service.DownloadAttachments(entityType, entityId, guid)); + await service.DownloadAttachments(entityType, _entityId, guid)); // Assert await _writeService.DidNotReceive() @@ -115,20 +113,19 @@ public async Task DownloadAttachment_FailedWriteAttachment() var bytes = Encoding.UTF8.GetBytes("Test"); var guid = Guid.NewGuid(); var entityType = Constants.TestCaseEntityType; - var entityId = "123"; - _client.GetAttachmentsByEntityId(entityType, entityId) + _client.GetAttachmentsByEntityId(entityType, _entityId) .Returns(_attachments); - _client.DownloadAttachmentById(Arg.Any()) + _client.DownloadAttachmentById(_attachments[0].Id) .Returns(bytes); - _writeService.WriteAttachment(guid, bytes, Arg.Any()) + _writeService.WriteAttachment(guid, bytes, _attachments[0].Attributes.Name) .Throws(new Exception("Failed to write attachment")); var service = new AttachmentService(_logger, _client, _writeService); // Act Assert.ThrowsAsync(async () => - await service.DownloadAttachments(entityType, entityId, guid)); + await service.DownloadAttachments(entityType, _entityId, guid)); } } From bb74570ca989c616a667055ca1acdd0b93ed8e2e Mon Sep 17 00:00:00 2001 From: "pavel.butuzov" Date: Thu, 16 Nov 2023 17:04:47 +0300 Subject: [PATCH 4/4] Added changes from code review. --- .../PractiTestExporter/Models/Constants.cs | 1 - .../Services/TestCaseService.cs | 3 ++- .../AttributeServiceTests.cs | 4 ++-- .../ExportServiceTests.cs | 14 ++++------- .../TestCaseServiceTests.cs | 23 ++++++++++--------- 5 files changed, 21 insertions(+), 24 deletions(-) diff --git a/Migrators/PractiTestExporter/Models/Constants.cs b/Migrators/PractiTestExporter/Models/Constants.cs index 0d369b5..7ee0b12 100644 --- a/Migrators/PractiTestExporter/Models/Constants.cs +++ b/Migrators/PractiTestExporter/Models/Constants.cs @@ -7,5 +7,4 @@ public class Constants public const string DateCustomFieldType = "date"; public const string TestCaseEntityType = "test"; public const string StepEntityType = "step"; - public const int Duration = 10000; } diff --git a/Migrators/PractiTestExporter/Services/TestCaseService.cs b/Migrators/PractiTestExporter/Services/TestCaseService.cs index c010f9e..8f71d57 100644 --- a/Migrators/PractiTestExporter/Services/TestCaseService.cs +++ b/Migrators/PractiTestExporter/Services/TestCaseService.cs @@ -13,6 +13,7 @@ public class TestCaseService : ITestCaseService private readonly IAttachmentService _attachmentService; private readonly Dictionary _sharedSteps; private readonly Dictionary _testCases; + public const int _duration = 10000; public TestCaseService(ILogger logger, IClient client, IAttachmentService attachmentService) { @@ -85,7 +86,7 @@ private async Task ConvertTestCases( Steps = steps, PreconditionSteps = ConvertPreconditionSteps(practiTestTestCase.Attributes.Preconditions), PostconditionSteps = new List(), - Duration = Constants.Duration, + Duration = _duration, Attributes = attributes, Tags = practiTestTestCase.Attributes.Tags, Attachments = attachments, diff --git a/Migrators/PractiTestExporterTests/AttributeServiceTests.cs b/Migrators/PractiTestExporterTests/AttributeServiceTests.cs index 1e562bc..38d37a3 100644 --- a/Migrators/PractiTestExporterTests/AttributeServiceTests.cs +++ b/Migrators/PractiTestExporterTests/AttributeServiceTests.cs @@ -99,7 +99,7 @@ public async Task GetCustomAttributes_FailedGetCustomFieldValues() _client.GetCustomFields() .Returns(_customFields); - _client.GetListCustomFieldById(Arg.Any()) + _client.GetListCustomFieldById(_customFields[0].Id) .ThrowsAsync(new Exception("Failed to get custom field values")); var service = new AttributeService(_logger, _client); @@ -116,7 +116,7 @@ public async Task GetCustomAttributes_Success() _client.GetCustomFields() .Returns(_customFields); - _client.GetListCustomFieldById(Arg.Any()) + _client.GetListCustomFieldById(_customFields[0].Id) .Returns(_listCustomField); var service = new AttributeService(_logger, _client); diff --git a/Migrators/PractiTestExporterTests/ExportServiceTests.cs b/Migrators/PractiTestExporterTests/ExportServiceTests.cs index ac73af6..249c9dc 100644 --- a/Migrators/PractiTestExporterTests/ExportServiceTests.cs +++ b/Migrators/PractiTestExporterTests/ExportServiceTests.cs @@ -20,7 +20,6 @@ public class ExportServiceTests private ITestCaseService _testCaseService; private IWriteService _writeService; private IAttributeService _attributeService; - private PractiTestProject _project; private AttributeData _attributeData; private TestCaseData _testCaseData; @@ -167,7 +166,7 @@ public async Task ExportProject_FailedWriteSharedStep() _attributeService.ConvertCustomAttributes() .Returns(_attributeData); - _testCaseService.ConvertTestCases(Arg.Any(), Arg.Any>()) + _testCaseService.ConvertTestCases(Arg.Any(), _attributeData.AttributeMap) .Returns(_testCaseData); _writeService.WriteSharedStep(_testCaseData.SharedSteps[0]) @@ -197,7 +196,7 @@ public async Task ExportProject_FailedWriteTestCase() _attributeService.ConvertCustomAttributes() .Returns(_attributeData); - _testCaseService.ConvertTestCases(Arg.Any(), Arg.Any>()) + _testCaseService.ConvertTestCases(Arg.Any(), _attributeData.AttributeMap) .Returns(_testCaseData); _writeService.WriteTestCase(_testCaseData.TestCases[0]) @@ -226,7 +225,7 @@ public async Task ExportProject_FailedWriteMainJson() _attributeService.ConvertCustomAttributes() .Returns(_attributeData); - _testCaseService.ConvertTestCases(Arg.Any(), Arg.Any>()) + _testCaseService.ConvertTestCases(Arg.Any(), _attributeData.AttributeMap) .Returns(_testCaseData); _writeService.WriteMainJson(Arg.Any()) @@ -255,16 +254,13 @@ public async Task ExportProject_Success() _attributeService.ConvertCustomAttributes() .Returns(_attributeData); - _testCaseService.ConvertTestCases(Arg.Any(), Arg.Any>()) + _testCaseService.ConvertTestCases(Arg.Any(), _attributeData.AttributeMap) .Returns(_testCaseData); - _writeService.WriteMainJson(Arg.Any()) - .Throws(new Exception("Failed to write test case")); - var exportService = new ExportService(_logger, _client, _writeService, _testCaseService, _attributeService); // Act - Assert.ThrowsAsync(async () => await exportService.ExportProject()); + await exportService.ExportProject(); // Assert await _writeService.Received() diff --git a/Migrators/PractiTestExporterTests/TestCaseServiceTests.cs b/Migrators/PractiTestExporterTests/TestCaseServiceTests.cs index 02a660c..d8e336c 100644 --- a/Migrators/PractiTestExporterTests/TestCaseServiceTests.cs +++ b/Migrators/PractiTestExporterTests/TestCaseServiceTests.cs @@ -4,6 +4,7 @@ using PractiTestExporter.Client; using PractiTestExporter.Models; using PractiTestExporter.Services; +using Constants = PractiTestExporter.Models.Constants; namespace PractiTestExporterTests; @@ -189,10 +190,10 @@ public async Task ConvertTestCases_FailedStepsByTestCaseId() _client.GetTestCases() .Returns(_tests); - _attachmentService.DownloadAttachments(Arg.Any(), Arg.Any(), Arg.Any()) + _attachmentService.DownloadAttachments(Constants.TestCaseEntityType, _tests[0].Id, Arg.Any()) .Returns(_attachments); - _client.GetStepsByTestCaseId(Arg.Any()) + _client.GetStepsByTestCaseId(_tests[0].Id) .Throws(new Exception("Failed to get steps")); var testCaseService = new TestCaseService(_logger, _client, _attachmentService); @@ -213,10 +214,10 @@ public async Task ConvertTestCases_FailedGetTestCaseById() _client.GetStepsByTestCaseId(_tests[0].Id) .Returns(_steps); - _attachmentService.DownloadAttachments(Arg.Any(), Arg.Any(), Arg.Any()) + _attachmentService.DownloadAttachments(Constants.StepEntityType, _steps[0].Id, Arg.Any()) .Returns(_attachments); - _client.GetTestCaseById(Arg.Any()) + _client.GetTestCaseById(_sharedSteps[0].Id) .Throws(new Exception("Failed to get test case")); var testCaseService = new TestCaseService(_logger, _client, _attachmentService); @@ -237,13 +238,13 @@ public async Task ConvertTestCases_FailedDownloadAttachment() _client.GetStepsByTestCaseId(_tests[0].Id) .Returns(_steps); - _client.GetTestCaseById(Arg.Any()) + _client.GetTestCaseById(_sharedSteps[0].Id) .Returns(_sharedSteps[0]); _client.GetStepsByTestCaseId(_sharedSteps[0].Id) .Returns(_sharedStepSteps); - _attachmentService.DownloadAttachments(Arg.Any(), Arg.Any(), Arg.Any()) + _attachmentService.DownloadAttachments(Constants.TestCaseEntityType, _sharedSteps[0].Id, Arg.Any()) .Throws(new Exception("Failed to download attachment")); var testCaseService = new TestCaseService(_logger, _client, _attachmentService); @@ -276,19 +277,19 @@ public async Task ConvertTestCases_Success_WithSharedStep() _client.GetStepsByTestCaseId(_sharedSteps[1].Id) .Returns(_sharedStepSteps); - _attachmentService.DownloadAttachments(Arg.Any(), _tests[1].Id, Arg.Any()) + _attachmentService.DownloadAttachments(Constants.TestCaseEntityType, _tests[1].Id, Arg.Any()) .Returns(_attachments); - _attachmentService.DownloadAttachments(Arg.Any(), _steps[0].Id, Arg.Any()) + _attachmentService.DownloadAttachments(Constants.StepEntityType, _steps[0].Id, Arg.Any()) .Returns(new List()); - _attachmentService.DownloadAttachments(Arg.Any(), _sharedSteps[0].Id, Arg.Any()) + _attachmentService.DownloadAttachments(Constants.TestCaseEntityType, _sharedSteps[0].Id, Arg.Any()) .Returns(new List()); - _attachmentService.DownloadAttachments(Arg.Any(), _sharedSteps[1].Id, Arg.Any()) + _attachmentService.DownloadAttachments(Constants.TestCaseEntityType, _sharedSteps[1].Id, Arg.Any()) .Returns(new List()); - _attachmentService.DownloadAttachments(Arg.Any(), _sharedStepSteps[0].Id, Arg.Any()) + _attachmentService.DownloadAttachments(Constants.StepEntityType, _sharedStepSteps[0].Id, Arg.Any()) .Returns(_attachments); var testCaseService = new TestCaseService(_logger, _client, _attachmentService);