From ffea86367db2daa6e3db478c3503ada2192a036a Mon Sep 17 00:00:00 2001 From: "pavel.butuzov" Date: Sun, 30 Jun 2024 23:31:18 +0300 Subject: [PATCH] Added the "automaticUpdationLinksToTestCases" configuration parameter. --- Tms.Adapter.Core/Client/ITmsClient.cs | 5 +- Tms.Adapter.Core/Client/TmsClient.cs | 78 +++++++++++++------ Tms.Adapter.Core/Configurator/Configurator.cs | 8 ++ Tms.Adapter.Core/Configurator/TmsSettings.cs | 1 + Tms.Adapter.Core/Service/AdapterManager.cs | 2 +- Tms.Adapter.Core/Tms.Adapter.Core.csproj | 2 +- Tms.Adapter.Core/Writer/Writer.cs | 34 ++++++-- Tms.Adapter.SpecFlowPlugin/README.md | 24 +++--- .../Tms.Adapter.SpecFlowPlugin.csproj | 2 +- Tms.Adapter.XUnit/README.md | 38 ++++----- Tms.Adapter.XUnit/Tms.Adapter.XUnit.csproj | 2 +- Tms.Adapter/README.md | 28 +++---- Tms.Adapter/Tms.Adapter.csproj | 2 +- .../Entities/Configuration/AdapterConfig.cs | 5 ++ .../ClassConfigurationProvider.cs | 1 + TmsRunner/Entities/Configuration/Config.cs | 3 +- .../Configuration/EnvConfigurationProvider.cs | 2 + TmsRunner/Entities/TmsSettings.cs | 1 + TmsRunner/Managers/TmsManager.cs | 70 +++++++++++++---- TmsRunner/Program.cs | 5 +- TmsRunner/Services/ProcessorService.cs | 26 ++++++- TmsRunner/TmsRunner.csproj | 2 +- 22 files changed, 244 insertions(+), 97 deletions(-) diff --git a/Tms.Adapter.Core/Client/ITmsClient.cs b/Tms.Adapter.Core/Client/ITmsClient.cs index f35e2c9..aba2b07 100644 --- a/Tms.Adapter.Core/Client/ITmsClient.cs +++ b/Tms.Adapter.Core/Client/ITmsClient.cs @@ -1,3 +1,4 @@ +using TestIT.ApiClient.Model; using Tms.Adapter.Core.Models; namespace Tms.Adapter.Core.Client; @@ -8,7 +9,9 @@ public interface ITmsClient Task CreateAutotest(TestContainer result, ClassContainer container); Task UpdateAutotest(TestContainer result, ClassContainer container); Task UpdateAutotest(string externalId, List links); - Task TryLinkAutoTestToWorkItems(string externalId, IEnumerable workItemIds); + Task LinkAutoTestToWorkItems(string autotestId, IEnumerable workItemIds); + Task DeleteAutoTestLinkFromWorkItem(string autotestId, string workItemId); + Task> GetWorkItemsLinkedToAutoTest(string autotestId); Task SubmitTestCaseResult(TestContainer result, ClassContainer container); Task UploadAttachment(string fileName, Stream content); Task CreateTestRun(); diff --git a/Tms.Adapter.Core/Client/TmsClient.cs b/Tms.Adapter.Core/Client/TmsClient.cs index 53fc999..6c8c50e 100644 --- a/Tms.Adapter.Core/Client/TmsClient.cs +++ b/Tms.Adapter.Core/Client/TmsClient.cs @@ -15,6 +15,8 @@ public class TmsClient : ITmsClient private readonly TestRunsApi _testRuns; private readonly AttachmentsApi _attachments; private readonly AutoTestsApi _autoTests; + private readonly int MAX_TRIES = 10; + private readonly int WAITING_TIME = 200; public TmsClient(ILogger logger, TmsSettings settings) { @@ -102,45 +104,75 @@ public async Task UpdateAutotest(string externalId, List links) _logger.LogDebug("Update autotest {ExternalId} is successfully", externalId); } - public async Task TryLinkAutoTestToWorkItems(string externalId, IEnumerable workItemIds) + public async Task LinkAutoTestToWorkItems(string autotestId, IEnumerable workItemIds) { - var autotest = await GetAutotestByExternalId(externalId); - - if (autotest == null) - { - _logger.LogError("Autotest with {ID} not found", externalId); - - return false; - } - foreach (var workItemId in workItemIds) { _logger.LogDebug( - "Linking autotest {AutotestId} to work item {WorkItemId}", - autotest.Id, + "Linking autotest {AutotestId} to workitem {WorkitemId}", + autotestId, workItemId); + for (var attempts = 0; attempts < MAX_TRIES; attempts++) + { + try + { + await _autoTests.LinkAutoTestToWorkItemAsync(autotestId, new LinkAutoTestToWorkItemRequest(workItemId ?? string.Empty)).ConfigureAwait(false); + _logger.LogDebug( + "Link autotest {AutotestId} to workitem {WorkitemId} is successfully", + autotestId, + workItemId); + + return; + } + catch (ApiException e) + { + _logger.LogError( + "Cannot link autotest {AutotestId} to work item {WorkItemId}: work item does not exist", + autotestId, + workItemId); + + Thread.Sleep(WAITING_TIME); + } + } + } + + } + + public async Task DeleteAutoTestLinkFromWorkItem(string autotestId, string workItemId) + { + _logger.LogDebug( + "Unlink autotest {AutotestId} from workitem {WorkitemId}", + autotestId, + workItemId); + + for (var attempts = 0; attempts < MAX_TRIES; attempts++) + { try { - await _autoTests.LinkAutoTestToWorkItemAsync(autotest.Id.ToString(), new LinkAutoTestToWorkItemRequest(workItemId)); + await _autoTests.DeleteAutoTestLinkFromWorkItemAsync(autotestId, workItemId); + _logger.LogDebug( + "Unlink autotest {AutotestId} from workitem {WorkitemId} is successfully", + autotestId, + workItemId); + + return; } - catch (ApiException e) when (e.Message.Contains("does not exist")) + catch (ApiException e) { _logger.LogError( - "Cannot link autotest {AutotestId} to work item {WorkItemId}: work item does not exist", - autotest.Id, + "Cannot link autotest {AutotestId} to work item {WorkitemId}", + autotestId, workItemId); - return false; + Thread.Sleep(WAITING_TIME); } - - _logger.LogDebug( - "Link autotest {AutotestId} to work item {WorkItemId} is successfully", - autotest.Id, - workItemId); } + } - return true; + public async Task> GetWorkItemsLinkedToAutoTest(string autotestId) + { + return await _autoTests.GetWorkItemsLinkedToAutoTestAsync(autotestId); } public async Task SubmitTestCaseResult(TestContainer result, ClassContainer container) diff --git a/Tms.Adapter.Core/Configurator/Configurator.cs b/Tms.Adapter.Core/Configurator/Configurator.cs index 3d55deb..769c79d 100644 --- a/Tms.Adapter.Core/Configurator/Configurator.cs +++ b/Tms.Adapter.Core/Configurator/Configurator.cs @@ -13,6 +13,7 @@ public static class Configurator private const string TmsTestRunId = "TMS_TEST_RUN_ID"; private const string TmsTestRunName = "TMS_TEST_RUN_NAME"; private const string TmsAutomaticCreationTestCases = "TMS_AUTOMATIC_CREATION_TEST_CASES"; + private const string TmsAutomaticUpdationLinksToTestCases = "TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES"; private const string TmsCertValidation = "TMS_CERT_VALIDATION"; private const string ConfigFile = "TMS_CONFIG_FILE"; private static readonly JsonSerializerOptions SerializerOptions = new() { PropertyNameCaseInsensitive = true }; @@ -22,6 +23,7 @@ public static TmsSettings GetConfig() var config = new TmsSettings { AutomaticCreationTestCases = false, + AutomaticUpdationLinksToTestCases = false, CertValidation = true }; @@ -98,6 +100,12 @@ private static void ApplyEnv(TmsSettings settings) settings.AutomaticCreationTestCases = value; } + var updateLinksToTestCase = Environment.GetEnvironmentVariable(TmsAutomaticUpdationLinksToTestCases); + if (bool.TryParse(updateLinksToTestCase, out var updateLinks) && updateLinks) + { + settings.AutomaticUpdationLinksToTestCases = updateLinks; + } + if (bool.TryParse(Environment.GetEnvironmentVariable(TmsCertValidation), out var validCert) && !validCert) { settings.CertValidation = false; diff --git a/Tms.Adapter.Core/Configurator/TmsSettings.cs b/Tms.Adapter.Core/Configurator/TmsSettings.cs index eeacfeb..71cfb66 100644 --- a/Tms.Adapter.Core/Configurator/TmsSettings.cs +++ b/Tms.Adapter.Core/Configurator/TmsSettings.cs @@ -16,6 +16,7 @@ public string Url public string TestRunId { get; set; } public string TestRunName { get; set; } public bool AutomaticCreationTestCases { get; set; } + public bool AutomaticUpdationLinksToTestCases { get; set; } public bool CertValidation { get; set; } public bool IsDebug { get; set; } } \ No newline at end of file diff --git a/Tms.Adapter.Core/Service/AdapterManager.cs b/Tms.Adapter.Core/Service/AdapterManager.cs index f5713cb..601a20f 100644 --- a/Tms.Adapter.Core/Service/AdapterManager.cs +++ b/Tms.Adapter.Core/Service/AdapterManager.cs @@ -48,7 +48,7 @@ public AdapterManager() _logger = logger.CreateLogger(); _client = new TmsClient(logger.CreateLogger(), config); _storage = new ResultStorage(); - _writer = new Writer.Writer(logger.CreateLogger(), _client); + _writer = new Writer.Writer(logger.CreateLogger(), _client, config); } public virtual AdapterManager StartTestContainer(ClassContainer container) diff --git a/Tms.Adapter.Core/Tms.Adapter.Core.csproj b/Tms.Adapter.Core/Tms.Adapter.Core.csproj index 9197f7a..2931336 100644 --- a/Tms.Adapter.Core/Tms.Adapter.Core.csproj +++ b/Tms.Adapter.Core/Tms.Adapter.Core.csproj @@ -1,7 +1,7 @@  - 1.6.0 + 1.6.1 netstandard2.1 enable true diff --git a/Tms.Adapter.Core/Writer/Writer.cs b/Tms.Adapter.Core/Writer/Writer.cs index 238f370..6c792d0 100644 --- a/Tms.Adapter.Core/Writer/Writer.cs +++ b/Tms.Adapter.Core/Writer/Writer.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.Logging; +using Tms.Adapter.Core.Configurator; using Tms.Adapter.Core.Client; using Tms.Adapter.Core.Models; @@ -8,11 +9,13 @@ public class Writer : IWriter { private readonly ILogger _logger; private readonly ITmsClient _client; + private readonly TmsSettings _tmsSettings; - public Writer(ILogger logger, ITmsClient client) + public Writer(ILogger logger, ITmsClient client, TmsSettings tmsSettings) { _logger = logger; _client = client; + _tmsSettings = tmsSettings; } public async Task Write(TestContainer result, ClassContainer container) @@ -44,10 +47,7 @@ public async Task Write(TestContainer result, ClassContainer container) if (result.WorkItemIds.Count > 0) { - if (!await _client.TryLinkAutoTestToWorkItems(result.ExternalId, result.WorkItemIds)) - { - return; - } + await UpdateTestLinkToWorkItems(result.ExternalId, result.WorkItemIds); } await _client.SubmitTestCaseResult(result, container); @@ -59,4 +59,28 @@ public async Task Write(TestContainer result, ClassContainer container) _logger.LogError(e, "Can not write autotest with ID {ID}", result.ExternalId); } } + + private async Task UpdateTestLinkToWorkItems(string autoTestId, List workItemIds) + { + var linkedWorkItems = await _client.GetWorkItemsLinkedToAutoTest(autoTestId); + + foreach (var linkedWorkItem in linkedWorkItems) + { + var linkedWorkItemId = linkedWorkItem.GlobalId.ToString(); + + if (workItemIds.Contains(linkedWorkItemId)) + { + workItemIds.Remove(linkedWorkItemId); + + continue; + } + + if (_tmsSettings.AutomaticUpdationLinksToTestCases) + { + await _client.DeleteAutoTestLinkFromWorkItem(autoTestId, linkedWorkItemId); + } + } + + await _client.LinkAutoTestToWorkItems(autoTestId, workItemIds); + } } \ No newline at end of file diff --git a/Tms.Adapter.SpecFlowPlugin/README.md b/Tms.Adapter.SpecFlowPlugin/README.md index f0c3b0b..aa2e35a 100644 --- a/Tms.Adapter.SpecFlowPlugin/README.md +++ b/Tms.Adapter.SpecFlowPlugin/README.md @@ -32,17 +32,18 @@ Also you need to add following lines to `specflow.json`: ### Configuration -| Description | File property | Environment variable | -|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|-----------------------------------| -| Location of the TMS instance | url | TMS_URL | -| API secret key [How to getting API secret key?](https://github.com/testit-tms/.github/tree/main/configuration#privatetoken) | privateToken | TMS_PRIVATE_TOKEN | -| ID of project in TMS instance [How to getting project ID?](https://github.com/testit-tms/.github/tree/main/configuration#projectid) | projectId | TMS_PROJECT_ID | -| ID of configuration in TMS instance [How to getting configuration ID?](https://github.com/testit-tms/.github/tree/main/configuration#configurationid) | configurationId | TMS_CONFIGURATION_ID | -| ID of the created test run in TMS instance. If you don't provide a test run ID, the adapter will automatically create one. | testRunId | TMS_TEST_RUN_ID | -| Parameter for specifying the name of test run in TMS instance (**It's optional**). If it is not provided, it is created automatically | testRunName | TMS_TEST_RUN_NAME | -| It enables/disables certificate validation (**It's optional**). Default value - true | certValidation | TMS_CERT_VALIDATION | -| Mode of automatic creation test cases (**It's optional**). Default value - false. The adapter supports following modes:
true - in this mode, the adapter will create a test case linked to the created autotest (not to the updated autotest)
false - in this mode, the adapter will not create a test case | automaticCreationTestCases | TMS_AUTOMATIC_CREATION_TEST_CASES | -| Enable debug logs (**It's optional**). Default value - false | isDebug | - | +| Description | File property | Environment variable | +|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|--------------------------------------------| +| Location of the TMS instance | url | TMS_URL | +| API secret key [How to getting API secret key?](https://github.com/testit-tms/.github/tree/main/configuration#privatetoken) | privateToken | TMS_PRIVATE_TOKEN | +| ID of project in TMS instance [How to getting project ID?](https://github.com/testit-tms/.github/tree/main/configuration#projectid) | projectId | TMS_PROJECT_ID | +| ID of configuration in TMS instance [How to getting configuration ID?](https://github.com/testit-tms/.github/tree/main/configuration#configurationid) | configurationId | TMS_CONFIGURATION_ID | +| ID of the created test run in TMS instance. If you don't provide a test run ID, the adapter will automatically create one. | testRunId | TMS_TEST_RUN_ID | +| Parameter for specifying the name of test run in TMS instance (**It's optional**). If it is not provided, it is created automatically | testRunName | TMS_TEST_RUN_NAME | +| It enables/disables certificate validation (**It's optional**). Default value - true | certValidation | TMS_CERT_VALIDATION | +| Mode of automatic creation test cases (**It's optional**). Default value - false. The adapter supports following modes:
true - in this mode, the adapter will create a test case linked to the created autotest (not to the updated autotest)
false - in this mode, the adapter will not create a test case | automaticCreationTestCases | TMS_AUTOMATIC_CREATION_TEST_CASES | +| Mode of automatic updation links to test cases (**It's optional**). Default value - false. The adapter supports following modes:
true - in this mode, the adapter will update links to test cases
false - in this mode, the adapter will not update link to test cases | automaticUpdationLinksToTestCases | TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES | +| Enable debug logs (**It's optional**). Default value - false | isDebug | - | #### File @@ -57,6 +58,7 @@ Create **Tms.config.json** file in the project directory: "testRunId": "TEST_RUN_ID", "testRunName": "TEST_RUN_NAME", "automaticCreationTestCases": false, + "automaticUpdationLinksToTestCases": false, "certValidation": true, "isDebug": true } diff --git a/Tms.Adapter.SpecFlowPlugin/Tms.Adapter.SpecFlowPlugin.csproj b/Tms.Adapter.SpecFlowPlugin/Tms.Adapter.SpecFlowPlugin.csproj index 1c195db..a070bcb 100644 --- a/Tms.Adapter.SpecFlowPlugin/Tms.Adapter.SpecFlowPlugin.csproj +++ b/Tms.Adapter.SpecFlowPlugin/Tms.Adapter.SpecFlowPlugin.csproj @@ -1,7 +1,7 @@  - 1.6.0 + 1.6.1 netstandard2.1 enable true diff --git a/Tms.Adapter.XUnit/README.md b/Tms.Adapter.XUnit/README.md index 26c093f..30ae41a 100644 --- a/Tms.Adapter.XUnit/README.md +++ b/Tms.Adapter.XUnit/README.md @@ -22,16 +22,17 @@ dotnet package add TestIT.Adapter.Core ### Configuration -| Description | File property | Environment variable | -|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|-----------------------------------| -| Location of the TMS instance | url | TMS_URL | -| API secret key [How to getting API secret key?](https://github.com/testit-tms/.github/tree/main/configuration#privatetoken) | privateToken | TMS_PRIVATE_TOKEN | -| ID of project in TMS instance [How to getting project ID?](https://github.com/testit-tms/.github/tree/main/configuration#projectid) | projectId | TMS_PROJECT_ID | -| ID of configuration in TMS instance [How to getting configuration ID?](https://github.com/testit-tms/.github/tree/main/configuration#configurationid) | configurationId | TMS_CONFIGURATION_ID | -| ID of the created test run in TMS instance. | testRunId | TMS_TEST_RUN_ID | -| It enables/disables certificate validation (**It's optional**). Default value - true | certValidation | TMS_CERT_VALIDATION | -| Mode of automatic creation test cases (**It's optional**). Default value - false. The adapter supports following modes:
true - in this mode, the adapter will create a test case linked to the created autotest (not to the updated autotest)
false - in this mode, the adapter will not create a test case | automaticCreationTestCases | TMS_AUTOMATIC_CREATION_TEST_CASES | -| Enable debug logs (**It's optional**). Default value - false | isDebug | - | +| Description | File property | Environment variable | +|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|--------------------------------------------| +| Location of the TMS instance | url | TMS_URL | +| API secret key [How to getting API secret key?](https://github.com/testit-tms/.github/tree/main/configuration#privatetoken) | privateToken | TMS_PRIVATE_TOKEN | +| ID of project in TMS instance [How to getting project ID?](https://github.com/testit-tms/.github/tree/main/configuration#projectid) | projectId | TMS_PROJECT_ID | +| ID of configuration in TMS instance [How to getting configuration ID?](https://github.com/testit-tms/.github/tree/main/configuration#configurationid) | configurationId | TMS_CONFIGURATION_ID | +| ID of the created test run in TMS instance. If you don't provide a test run ID, the adapter will automatically create one. | testRunId | TMS_TEST_RUN_ID | +| It enables/disables certificate validation (**It's optional**). Default value - true | certValidation | TMS_CERT_VALIDATION | +| Mode of automatic creation test cases (**It's optional**). Default value - false. The adapter supports following modes:
true - in this mode, the adapter will create a test case linked to the created autotest (not to the updated autotest)
false - in this mode, the adapter will not create a test case | automaticCreationTestCases | TMS_AUTOMATIC_CREATION_TEST_CASES | +| Mode of automatic updation links to test cases (**It's optional**). Default value - false. The adapter supports following modes:
true - in this mode, the adapter will update links to test cases
false - in this mode, the adapter will not update link to test cases | automaticUpdationLinksToTestCases | TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES | +| Enable debug logs (**It's optional**). Default value - false | isDebug | - | #### File @@ -39,14 +40,15 @@ Create **Tms.config.json** file in the project directory: ```json { - "url": "URL", - "privateToken": "USER_PRIVATE_TOKEN", - "projectId": "PROJECT_ID", - "configurationId": "CONFIGURATION_ID", - "testRunId": "TEST_RUN_ID", - "automaticCreationTestCases": false, - "certValidation": true, - "isDebug": true + "url": "URL", + "privateToken": "USER_PRIVATE_TOKEN", + "projectId": "PROJECT_ID", + "configurationId": "CONFIGURATION_ID", + "testRunId": "TEST_RUN_ID", + "automaticCreationTestCases": false, + "automaticUpdationLinksToTestCases": false, + "certValidation": true, + "isDebug": true } ``` diff --git a/Tms.Adapter.XUnit/Tms.Adapter.XUnit.csproj b/Tms.Adapter.XUnit/Tms.Adapter.XUnit.csproj index 96b95fc..a6b6063 100644 --- a/Tms.Adapter.XUnit/Tms.Adapter.XUnit.csproj +++ b/Tms.Adapter.XUnit/Tms.Adapter.XUnit.csproj @@ -1,7 +1,7 @@  - 1.6.0 + 1.6.1 netstandard2.1 enable true diff --git a/Tms.Adapter/README.md b/Tms.Adapter/README.md index 316d553..a550575 100644 --- a/Tms.Adapter/README.md +++ b/Tms.Adapter/README.md @@ -27,18 +27,19 @@ dotnet package add TestIt.Adapter ### Configuration -| Description | File property | Environment variable | CLI argument | -|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|-----------------------------------|-------------------------------| -| Location of the TMS instance | url | TMS_URL | tmsUrl | -| API secret key [How to getting API secret key?](https://github.com/testit-tms/.github/tree/main/configuration#privatetoken) | privateToken | TMS_PRIVATE_TOKEN | tmsPrivateToken | -| ID of project in TMS instance [How to getting project ID?](https://github.com/testit-tms/.github/tree/main/configuration#projectid) | projectId | TMS_PROJECT_ID | tmsProjectId | -| ID of configuration in TMS instance [How to getting configuration ID?](https://github.com/testit-tms/.github/tree/main/configuration#configurationid) | configurationId | TMS_CONFIGURATION_ID | tmsConfigurationId | -| ID of the created test run in TMS instance.
It's necessary for **adapterMode** 0 or 1 | testRunId | TMS_TEST_RUN_ID | tmsTestRunId | -| Parameter for specifying the name of test run in TMS instance (**It's optional**). If it is not provided, it is created automatically | testRunName | TMS_TEST_RUN_NAME | tmsTestRunName | -| Adapter mode. Default value - 0. The adapter supports following modes:
0 - in this mode, the adapter filters tests by test run ID and configuration ID, and sends the results to the test run
1 - in this mode, the adapter sends all results to the test run without filtering
2 - in this mode, the adapter creates a new test run and sends results to the new test run | adapterMode | TMS_ADAPTER_MODE | tmsAdapterMode | -| It enables/disables certificate validation (**It's optional**). Default value - true | certValidation | TMS_CERT_VALIDATION | tmsCertValidation | -| Mode of automatic creation test cases (**It's optional**). Default value - false. The adapter supports following modes:
true - in this mode, the adapter will create a test case linked to the created autotest (not to the updated autotest)
false - in this mode, the adapter will not create a test case | automaticCreationTestCases | TMS_AUTOMATIC_CREATION_TEST_CASES | tmsAutomaticCreationTestCases | -| List of labels for filtering tests (**Optional**). It will only work with adapter mode 2. | - | - | tmsLabelsOfTestsToRun | +| Description | File property | Environment variable | CLI argument | +|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|--------------------------------------------|--------------------------------------| +| Location of the TMS instance | url | TMS_URL | tmsUrl | +| API secret key [How to getting API secret key?](https://github.com/testit-tms/.github/tree/main/configuration#privatetoken) | privateToken | TMS_PRIVATE_TOKEN | tmsPrivateToken | +| ID of project in TMS instance [How to getting project ID?](https://github.com/testit-tms/.github/tree/main/configuration#projectid) | projectId | TMS_PROJECT_ID | tmsProjectId | +| ID of configuration in TMS instance [How to getting configuration ID?](https://github.com/testit-tms/.github/tree/main/configuration#configurationid) | configurationId | TMS_CONFIGURATION_ID | tmsConfigurationId | +| ID of the created test run in TMS instance.
It's necessary for **adapterMode** 0 or 1 | testRunId | TMS_TEST_RUN_ID | tmsTestRunId | +| Parameter for specifying the name of test run in TMS instance (**It's optional**). If it is not provided, it is created automatically | testRunName | TMS_TEST_RUN_NAME | tmsTestRunName | +| Adapter mode. Default value - 0. The adapter supports following modes:
0 - in this mode, the adapter filters tests by test run ID and configuration ID, and sends the results to the test run
1 - in this mode, the adapter sends all results to the test run without filtering
2 - in this mode, the adapter creates a new test run and sends results to the new test run | adapterMode | TMS_ADAPTER_MODE | tmsAdapterMode | +| It enables/disables certificate validation (**It's optional**). Default value - true | certValidation | TMS_CERT_VALIDATION | tmsCertValidation | +| Mode of automatic creation test cases (**It's optional**). Default value - false. The adapter supports following modes:
true - in this mode, the adapter will create a test case linked to the created autotest (not to the updated autotest)
false - in this mode, the adapter will not create a test case | automaticCreationTestCases | TMS_AUTOMATIC_CREATION_TEST_CASES | tmsAutomaticCreationTestCases | +| Mode of automatic updation links to test cases (**It's optional**). Default value - false. The adapter supports following modes:
true - in this mode, the adapter will update links to test cases
false - in this mode, the adapter will not update link to test cases | automaticUpdationLinksToTestCases | TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES | tmsAutomaticUpdationLinksToTestCases | +| List of labels for filtering tests (**Optional**). It will only work with adapter mode 2. | - | - | tmsLabelsOfTestsToRun | #### File @@ -54,6 +55,7 @@ Create **Tms.config.json** file in the project directory: "testRunName": "TEST_RUN_NAME", "adapterMode": ADAPTER_MODE, "automaticCreationTestCases": AUTOMATIC_CREATION_TEST_CASES, + "automaticUpdationLinksToTestCases": AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES, "certValidation": CERT_VALIDATION } ``` @@ -64,7 +66,7 @@ Create **Tms.config.json** file in the project directory: ``` TmsRunner --runner "/usr/local/share/dotnet/sdk/6.0.302/vstest.console.dll" --testassembly "/tests/MsTest.dll" --tmsUrl=http://localhost:8080 --tmsPrivateToken=Token --tmsProjectId=f5da5bab-380a-4382-b36f-600083fdd795 --tmsConfigurationId=3a14fa45-b54e-4859-9998-cc502d4cc8c6 --tmsAdapterMode=0 --tmsTestRunId=a17269da-bc65-4671-90dd-d3e3da92af80 --tmsTestRunName=Regress --tmsAutomaticCreationTestCases=true --tmsCertValidation=true --tmsLabelsOfTestsToRun smoke,regress --debug +-tmsAdapterMode=0 --tmsTestRunId=a17269da-bc65-4671-90dd-d3e3da92af80 --tmsTestRunName=Regress --tmsAutomaticCreationTestCases=true --tmsAutomaticUpdationLinksToTestCases=true --tmsCertValidation=true --tmsLabelsOfTestsToRun smoke,regress --debug ``` * `runner` - path to vstest.console.dll or vstest.console.exe diff --git a/Tms.Adapter/Tms.Adapter.csproj b/Tms.Adapter/Tms.Adapter.csproj index cf3d0d3..1cdb862 100644 --- a/Tms.Adapter/Tms.Adapter.csproj +++ b/Tms.Adapter/Tms.Adapter.csproj @@ -1,7 +1,7 @@  - 1.6.0 + 1.6.1 netstandard2.1 enable true diff --git a/TmsRunner/Entities/Configuration/AdapterConfig.cs b/TmsRunner/Entities/Configuration/AdapterConfig.cs index 62003e7..3b1e74a 100644 --- a/TmsRunner/Entities/Configuration/AdapterConfig.cs +++ b/TmsRunner/Entities/Configuration/AdapterConfig.cs @@ -72,6 +72,9 @@ public string? LoggerPath [Option("tmsAutomaticCreationTestCases", Required = false, HelpText = "Set automatic creation test cases.")] public string? TmsAutomaticCreationTestCases { get; init; } + [Option("TmsAutomaticUpdationLinksToTestCases", Required = false, HelpText = "Set automatic updation links to test cases.")] + public string? TmsAutomaticUpdationLinksToTestCases { get; init; } + [Option("tmsCertValidation", Default = "true", Required = false, HelpText = "Set certificate validation.")] public string? TmsCertValidation { get; init; } @@ -89,8 +92,10 @@ public Config ToInternalConfig() TmsConfigFile = TmsConfigFile, TmsRunSettings = TmsRunSettings, TmsAutomaticCreationTestCases = TmsAutomaticCreationTestCases, + TmsAutomaticUpdationLinksToTestCases = TmsAutomaticUpdationLinksToTestCases, TmsCertValidation = TmsCertValidation, TmsLabelsOfTestsToRun = TmsLabelsOfTestsToRun + }; } diff --git a/TmsRunner/Entities/Configuration/ClassConfigurationProvider.cs b/TmsRunner/Entities/Configuration/ClassConfigurationProvider.cs index 0346743..5b913f0 100644 --- a/TmsRunner/Entities/Configuration/ClassConfigurationProvider.cs +++ b/TmsRunner/Entities/Configuration/ClassConfigurationProvider.cs @@ -18,6 +18,7 @@ public override void Load() { "ConfigFile", config.TmsConfigFile }, { "RunSettings", config.TmsRunSettings }, { "AutomaticCreationTestCases", config.TmsAutomaticCreationTestCases }, + { "AutomaticUpdationLinksToTestCases", config.TmsAutomaticUpdationLinksToTestCases }, { "CertValidation", config.TmsCertValidation } }; diff --git a/TmsRunner/Entities/Configuration/Config.cs b/TmsRunner/Entities/Configuration/Config.cs index 95d278a..fc2bd1e 100644 --- a/TmsRunner/Entities/Configuration/Config.cs +++ b/TmsRunner/Entities/Configuration/Config.cs @@ -12,6 +12,7 @@ public sealed record Config public string? TmsConfigFile; public string? TmsRunSettings; public string? TmsAutomaticCreationTestCases; + public string? TmsAutomaticUpdationLinksToTestCases; public string? TmsCertValidation; public string? TmsLabelsOfTestsToRun; -} \ No newline at end of file +} diff --git a/TmsRunner/Entities/Configuration/EnvConfigurationProvider.cs b/TmsRunner/Entities/Configuration/EnvConfigurationProvider.cs index 5d92200..dd16682 100644 --- a/TmsRunner/Entities/Configuration/EnvConfigurationProvider.cs +++ b/TmsRunner/Entities/Configuration/EnvConfigurationProvider.cs @@ -13,6 +13,7 @@ public sealed class EnvConfigurationProvider : ConfigurationProvider private const string EnvTmsAdapterMode = "TMS_ADAPTER_MODE"; private const string EnvTmsRunSettings = "TMS_RUN_SETTINGS"; private const string EnvTmsAutomaticCreationTestCases = "TMS_AUTOMATIC_CREATION_TEST_CASES"; + private const string EnvTmsAutomaticUpdationLinksToTestCases = "TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES"; private const string EnvTmsCertValidation = "TMS_CERT_VALIDATION"; public override void Load() @@ -28,6 +29,7 @@ public override void Load() { "AdapterMode", Environment.GetEnvironmentVariable(EnvTmsAdapterMode) }, { "RunSettings", Environment.GetEnvironmentVariable(EnvTmsRunSettings) }, { "AutomaticCreationTestCases", Environment.GetEnvironmentVariable(EnvTmsAutomaticCreationTestCases) }, + { "AutomaticUpdationLinksToTestCases", Environment.GetEnvironmentVariable(EnvTmsAutomaticUpdationLinksToTestCases) }, { "CertValidation", Environment.GetEnvironmentVariable(EnvTmsCertValidation) }, }; diff --git a/TmsRunner/Entities/TmsSettings.cs b/TmsRunner/Entities/TmsSettings.cs index 4df7b22..d3132aa 100644 --- a/TmsRunner/Entities/TmsSettings.cs +++ b/TmsRunner/Entities/TmsSettings.cs @@ -18,5 +18,6 @@ public string? Url public int AdapterMode { get; set; } public string? RunSettings { get; set; } public bool AutomaticCreationTestCases { get; set; } + public bool AutomaticUpdationLinksToTestCases { get; set; } public bool CertValidation { get; set; } } \ No newline at end of file diff --git a/TmsRunner/Managers/TmsManager.cs b/TmsRunner/Managers/TmsManager.cs index 49e9204..2183057 100644 --- a/TmsRunner/Managers/TmsManager.cs +++ b/TmsRunner/Managers/TmsManager.cs @@ -14,6 +14,9 @@ public sealed class TmsManager(ILogger logger, ITestRunsApiAsync testRunsApi, TmsSettings settings) { + private readonly int MAX_TRIES = 10; + private readonly int WAITING_TIME = 200; + public async Task CreateTestRunAsync() { var createTestRunRequestBody = new CreateEmptyRequest @@ -120,7 +123,7 @@ public async Task UpdateAutotestAsync(AutoTest dto) logger.LogDebug("Update autotest {@Autotest} is successfully", model); } - public async Task TryLinkAutoTestToWorkItemAsync(string autotestId, IEnumerable workItemIds) + public async Task LinkAutoTestToWorkItemAsync(string autotestId, IEnumerable workItemIds) { foreach (var workItemId in workItemIds) { @@ -129,26 +132,65 @@ public async Task TryLinkAutoTestToWorkItemAsync(string autotestId, IEnume autotestId, workItemId); + for (var attempts = 0; attempts < MAX_TRIES; attempts++) + { + try + { + await autoTestsApi.LinkAutoTestToWorkItemAsync(autotestId, new LinkAutoTestToWorkItemRequest(workItemId ?? string.Empty)).ConfigureAwait(false); + logger.LogDebug( + "Link autotest {AutotestId} to workitem {WorkitemId} is successfully", + autotestId, + workItemId); + + return; + } + catch (ApiException e) + { + logger.LogError( + "Cannot link autotest {AutotestId} to work item {WorkItemId}", + autotestId, + workItemId); + + Thread.Sleep(WAITING_TIME); + } + } + } + + } + + public async Task DeleteAutoTestLinkFromWorkItemAsync(string autotestId, string workItemId) + { + logger.LogDebug( + "Unlink autotest {AutotestId} from workitem {WorkitemId}", + autotestId, + workItemId); + + for (var attempts = 0; attempts < MAX_TRIES; attempts++) + { try { - await autoTestsApi.LinkAutoTestToWorkItemAsync(autotestId, new LinkAutoTestToWorkItemRequest(workItemId ?? string.Empty)).ConfigureAwait(false); + await autoTestsApi.DeleteAutoTestLinkFromWorkItemAsync(autotestId, workItemId); + logger.LogDebug( + "Unlink autotest {AutotestId} from workitem {WorkitemId} is successfully", + autotestId, + workItemId); + + return; } - catch (ApiException e) when (e.Message.Contains("does not exist")) + catch (ApiException e) { logger.LogError( - "Cannot link autotest {AutotestId} to work item {WorkItemId}: work item does not exist", - autotestId, - workItemId); + "Cannot link autotest {AutotestId} to work item {WorkitemId}", + autotestId, + workItemId); - return false; + Thread.Sleep(WAITING_TIME); } - - logger.LogDebug( - "Link autotest {AutotestId} to workitem {WorkitemId} is successfully", - autotestId, - workItemId); } + } - return true; + public async Task> GetWorkItemsLinkedToAutoTestAsync(string autotestId) + { + return await autoTestsApi.GetWorkItemsLinkedToAutoTestAsync(autotestId); } -} \ No newline at end of file +} diff --git a/TmsRunner/Program.cs b/TmsRunner/Program.cs index d2c6914..13dbc88 100644 --- a/TmsRunner/Program.cs +++ b/TmsRunner/Program.cs @@ -55,7 +55,10 @@ private static AdapterConfig GetAdapterConfiguration(IEnumerable args) TmsTestRunName = ac.TmsTestRunName, TmsAdapterMode = ac.TmsAdapterMode, TmsConfigFile = ac.TmsConfigFile, - TmsLabelsOfTestsToRun = ac.TmsLabelsOfTestsToRun + TmsLabelsOfTestsToRun = ac.TmsLabelsOfTestsToRun, + TmsAutomaticCreationTestCases = ac.TmsAutomaticCreationTestCases, + TmsAutomaticUpdationLinksToTestCases = ac.TmsAutomaticUpdationLinksToTestCases, + TmsCertValidation = ac.TmsCertValidation }; }); diff --git a/TmsRunner/Services/ProcessorService.cs b/TmsRunner/Services/ProcessorService.cs index 111fb3e..382bb6b 100644 --- a/TmsRunner/Services/ProcessorService.cs +++ b/TmsRunner/Services/ProcessorService.cs @@ -203,10 +203,7 @@ public async Task ProcessAutoTestAsync(TestResult testResult) if (autoTest.WorkItemIds.Count > 0) { - if (!await apiClient.TryLinkAutoTestToWorkItemAsync(existAutotest.Id.ToString(), autoTest.WorkItemIds).ConfigureAwait(false)) - { - return; - } + await UpdateTestLinkToWorkItems(existAutotest.Id.ToString(), autoTest.WorkItemIds); } if (!string.IsNullOrEmpty(testResult.ErrorMessage)) @@ -220,6 +217,27 @@ public async Task ProcessAutoTestAsync(TestResult testResult) await apiClient.SubmitResultToTestRunAsync(tmsSettings.TestRunId, autoTestResultRequestBody).ConfigureAwait(false); } + private async Task UpdateTestLinkToWorkItems(string autoTestId, List workItemIds) + { + var linkedWorkItems = await apiClient.GetWorkItemsLinkedToAutoTestAsync(autoTestId); + + foreach (var linkedWorkItem in linkedWorkItems) { + var linkedWorkItemId = linkedWorkItem.GlobalId.ToString(); + + if (workItemIds.Contains(linkedWorkItemId)) { + workItemIds.Remove(linkedWorkItemId); + + continue; + } + + if (tmsSettings.AutomaticUpdationLinksToTestCases) { + await apiClient.DeleteAutoTestLinkFromWorkItemAsync(autoTestId, linkedWorkItemId); + } + } + + await apiClient.LinkAutoTestToWorkItemAsync(autoTestId, workItemIds); + } + private static AutoTestResult GetAutoTestResultsForTestRunModel(AutoTest autoTest, TestResult testResult, string traceJson, diff --git a/TmsRunner/TmsRunner.csproj b/TmsRunner/TmsRunner.csproj index 7a3d99c..ed29087 100644 --- a/TmsRunner/TmsRunner.csproj +++ b/TmsRunner/TmsRunner.csproj @@ -1,7 +1,7 @@  - 1.6.0 + 1.6.1 Exe enable enable