{"id":90259,"date":"2020-10-29T15:19:10","date_gmt":"2020-10-29T15:19:10","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=youtrack&#038;p=90259"},"modified":"2020-10-29T15:19:10","modified_gmt":"2020-10-29T15:19:10","slug":"make-it-workflow-partie-13-prise-en-charge-des-scenarios-de-gestion-de-tests","status":"publish","type":"youtrack","link":"https:\/\/blog.jetbrains.com\/fr\/youtrack\/2020\/10\/make-it-workflow-partie-13-prise-en-charge-des-scenarios-de-gestion-de-tests\/","title":{"rendered":"Make It Workflow \u2014 Partie 13 : Prise en charge des sc\u00e9narios de gestion de tests"},"content":{"rendered":"<p><a href=\"https:\/\/blog.jetbrains.com\/youtrack\/2020\/10\/make-it-workflow-part-13-supporting-test-management-scenarios\/\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/YT_workflow_en-1.png\" alt=\"\" \/><\/a><\/p>\n<p>Bienvenue \u00e0 nouveau dans notre s\u00e9rie \u00ab\u00a0Make It Workflow\u00a0\u00bb\u00a0! Nous avons re\u00e7u plusieurs demandes de la communaut\u00e9 concernant les fonctionnalit\u00e9s de YouTrack pouvant \u00eatre utilis\u00e9es par les \u00e9quipe d&#8217;assurance qualit\u00e9. Aujourd&#8217;hui, nous allons voir comment maintenir les sc\u00e9narios de gestion des tests (Test Management Scenarios) dans YouTrack. Cet article explique comment configurer YouTrack afin de conserver la fonctionnalit\u00e9 de gestion des tests au sein m\u00eame de YouTrack et de ne pas avoir \u00e0 utiliser de solutions tierces. Cette approche vous permet d&#8217;\u00e9conomiser sur les co\u00fbts de licence et de faciliter le d\u00e9roulement du processus de gestion de tests.<\/p>\n<p>Cet article est destin\u00e9 aux gestionnaires de tests et \u00e0 toute personne int\u00e9ress\u00e9e par les workflows de YouTrack. Vous y trouverez notamment un exemple pratique d&#8217;\u00e9laboration d&#8217;un processus de test dans YouTrack, avec des recommandations pour le param\u00e9trage des projets et des tickets et une description de l&#8217;impl\u00e9mentation des sc\u00e9narios de gestion de tests.<\/p>\n<p><span id=\"more-77371\"><\/span><\/p>\n<p>Nous avons \u00e9galement \u00e9tabli une liste de blocs de code de workflow pr\u00eats \u00e0 l&#8217;emploi pour l&#8217;automatisation des processus de gestion des tests. Ces blocs de code facilitent entre autres l&#8217;association des cas de test \u00e0 l&#8217;ex\u00e9cution de test sp\u00e9cifique, le clonage d&#8217;une ex\u00e9cution de test, l&#8217;affichage de suggestions pour le prochain test.<br \/>\n<a name=\"ref1\"><\/a><\/p>\n<h2>Param\u00e8tres pour les projets de gestion de tests dans YouTrack<\/h2>\n<p>Pour vos projets, vous pouvez utiliser des types de tickets sp\u00e9cifiques \u00e0 la gestion des tests comme Test Case (cas de tests), Test Suite (un ensemble de cas de tests), Test Run (un ensemble de cas de tests ou de suites de tests affect\u00e9s \u00e0 un cycle de test sp\u00e9cifique) et Test Case Executions pour une ex\u00e9cution de test sp\u00e9cifique. Vous devez <a href=\"https:\/\/www.jetbrains.com\/help\/youtrack\/standalone\/Manage-Custom-Fields-Per-Project.html#add-custom-field-to-project\" target=\"_blank\" rel=\"noopener\">configurer<\/a> les types de ticket requis pour votre projet TMS. Il existe 3 types de <a href=\"https:\/\/www.jetbrains.com\/help\/youtrack\/standalone\/Link-Types.html\" target=\"_blank\" rel=\"noopener\">liens de tickets<\/a> pour \u00e9tablir les connexions et la pertinence entre vos t\u00e2ches de gestion de tests\u00a0:<\/p>\n<ul>\n<li>Les liens standards \u00ab\u00a0parent-subtasks\u00a0\u00bb maintiennent les relations entre ex\u00e9cutions de tests et ex\u00e9cutions de cas de tests, ainsi qu&#8217;entre suite de tests et cas de tests. <\/li>\n<li>Le lien personnalis\u00e9 \u00ab\u00a0Execution\u00a0\u00bb maintient les relations entre cas de test et ex\u00e9cution de cas de test. <\/li>\n<li>Le lien personnalis\u00e9 \u00ab\u00a0Related Bug\u00a0\u00bb maintient les relations entre les tests ayant \u00e9chou\u00e9 et les bugs attribu\u00e9s.<\/li>\n<\/ul>\n<p>Les crit\u00e8res de tests peuvent \u00eatre maintenus sous la forme d&#8217;un <a href=\"https:\/\/www.jetbrains.com\/help\/youtrack\/standalone\/create-articles.html\" target=\"_blank\" rel=\"noopener\">article<\/a> associ\u00e9 aux tickets dans un champ de texte.<br \/>En outre, vous pouvez d\u00e9finir des <a href=\"https:\/\/www.jetbrains.com\/help\/youtrack\/standalone\/Manage-Custom-Fields-Per-Project.html#add-custom-field-to-project\" target=\"_blank\" rel=\"noopener\">champs personnalis\u00e9s<\/a> pour vos t\u00e2ches de gestion de tests, tels que <em>Test mode<\/em>, <em>Category<\/em>, <em>Test flow<\/em>et <em>Application<\/em>, ainsi que des valeurs pr\u00e9d\u00e9finies (par exemple, des statuts de test pr\u00e9d\u00e9finis). Vous pouvez \u00e9galement utiliser des <a href=\"https:\/\/www.jetbrains.com\/help\/youtrack\/standalone\/conditional-custom-fields.html\" target=\"_blank\" rel=\"noopener\">champs conditionnels<\/a> lorsque vous devez afficher des informations sp\u00e9cifiquement pour un type de ticket.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/TMS0_1.png\" alt=\"\" \/><\/p>\n<p>Un ensemble de champs pr\u00e9d\u00e9finis pour les types de ticket \u00ab\u00a0Test Case\u00a0\u00bb (Cas de tests) et \u00ab\u00a0Test Run\u00a0\u00bb (\u00c9x\u00e9cution de tests) peut \u00eatre adapt\u00e9 en fonction des besoins de votre entreprise.<\/p>\n<h2>Configuration de Test Runs et Test Execution<\/h2>\n<p>Pour tester une version sp\u00e9cifique d&#8217;un produit par exemple, il faut cr\u00e9er une s\u00e9rie de tests et lui attribuer un certain nombre de suites et de cas de tests pertinents. Pour ce faire, suivez les \u00e9tapes suivantes\u00a0:<\/p>\n<ul>\n<li>Cr\u00e9ez un ticket de type \u00ab\u00a0Test Run\u00a0\u00bb. <\/li>\n<li>Utilisez le lien personnalis\u00e9 \u00ab\u00a0Assigned test case and test suite\u00a0\u00bb (\u00ab Cas de test et suite de tests affect\u00e9s \u00bb) pour faire le lien avec le ticket.<\/li>\n<li>Dans la fen\u00eatre contextuelle, pr\u00e9cisez les cas de tests \u00e0 inclure dans Test Run.<\/li>\n<\/ul>\n<p>Les \u00e9tapes du workflow \u00ab\u00a0Populate Test Run\u00a0\u00bb (Remplir la s\u00e9rie de tests) permettent \u00e0 votre \u00e9quipe d&#8217;assurance qualit\u00e9 d&#8217;\u00e9conomiser du temps et des efforts\u00a0:<\/p>\n<ul>\n<li>Des copies de toutes les suites de tests et de tous les cas de test s\u00e9lectionn\u00e9s sont cr\u00e9\u00e9es dans le syst\u00e8me. Tous les tickets seront de type \u00ab\u00a0Test Case Execution\u00a0\u00bb. <\/li>\n<li>Le type de lien \u00ab\u00a0Execution\u00a0\u00bb associera les ex\u00e9cutions de cas de tests aux cas de tests s\u00e9lectionn\u00e9s.<\/li>\n<li>Les tickets nouvellement cr\u00e9\u00e9s seront associ\u00e9s \u00e0 un Test Run en tant que ticket parent et \u00e0 ses sous-t\u00e2ches connexes.<\/li>\n<\/ul>\n<p>Voici comment cela fonctionne :<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/resources.jetbrains.com\/storage\/products\/blog\/wp-content\/uploads\/done1s720cut.gif\" alt=\"\" \/><\/p>\n<details>\n<summary>\n        \u00c9tendre le bloc de code<br \/>\n    <\/summary>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-title=\"\">\nvar entities = require(&#039;@jetbrains\/youtrack-scripting-api\/entities&#039;);\nvar workflow = require(&#039;@jetbrains\/youtrack-scripting-api\/workflow&#039;);\n\nexports.rule = entities.Issue.onChange({\n  title: &#039;Populate-test-run&#039;,\n  guard: function(ctx) {\n    var issue = ctx.issue;\n    return !issue.isChanged(&#039;project&#039;) &amp;&amp; issue.Type &amp;&amp; (issue.Type.name == ctx.Type.TestRun.name) &amp;&amp; issue.links[ctx.Execution.outward].added.isNotEmpty() &amp;&amp; issue.isReported;\n  },\n  action: function(ctx) {\n    var issue = ctx.issue;\n    var totalTestRuns = issue.links[ctx.Execution.outward].added.size;\n    issue.links[ctx.Execution.outward].added.forEach(function(TestCase) {\n      TestCase.links[ctx.Execution.inward].delete(issue);\n\n      var TestCaseRun = TestCase.copy();\n      TestCaseRun.Type = ctx.Type.TestExecution.name;\n      TestCaseRun.Status = ctx.Status.NoRun.name;\n      Object.keys(TestCaseRun.links).forEach(function(linkType) {\n       if (!TestCaseRun.links[linkType])\n        return;\n         TestCaseRun.links[linkType].clear();\n      });\n      TestCaseRun.summary = \"[TEST_CASE_EXECUTION\" + \"] [\" + TestCaseRun.summary + \"]\";\n\n      TestCaseRun.links[ctx.Subtask.inward].add(issue);\n      issue.links[ctx.Subtask.outward].add(TestCaseRun);\n      TestCaseRun.links[ctx.Execution.outward].add(TestCase);\n    });\n    issue.fields[&#039;Total number of test cases&#039;] = totalTestRuns;\n  },\n  requirements: {\n    Execution: {\n      type: entities.IssueLinkPrototype,\n      name: &#039;Execution&#039;,\n      inward: &#039;Execution&#039;,\n      outward: &#039;Assigned test case or test suite&#039;\n    },\n    Subtask: {\n      type: entities.IssueLinkPrototype,\n      name: &#039;Subtask&#039;,\n      inward: &#039;parent for&#039;,\n      outward: &#039;subtask of&#039;\n    },\n    Type: {\n      type: entities.EnumField.fieldType,\n      TestExecution: {\n        name: \"Test Case Execution\"\n      },\n      TestRun: {\n        name: \"Test Run\"\n      },\n      TestCase: {\n        name: \"Test Case\"\n      },\n      TestSuite: {\n        name: \"Test Suite\"\n      }\n    },\n    Total: {\n      type: entities.Field.integerType,\n      name: &#039;Total number of test cases&#039;\n    },\n    TotalFailed: {\n      type: entities.Field.integerType,\n      name: &#039;Number of failed test cases&#039;\n    },\n    TotalPassed: {\n      type: entities.Field.integerType,\n      name: &#039;Number of passed test cases&#039;\n    },\n    Status: {\n      type: entities.EnumField.fieldType,\n      InProgress: {\n        name: &#039;In Progress&#039;\n      },\n      Passed: {\n        name: &#039;Passed&#039;\n      },\n      Failed: {\n        name: &#039;Failed&#039;\n      },\n      NoRun: {\n        name: &#039;No Run&#039;\n      },\n    },\n  }\n});\n<\/pre>\n<p>\n<\/details>\n<h2>Maintenir les activit\u00e9s de tests<\/h2>\n<p>Une fois les Test Runs enti\u00e8rement configur\u00e9s, vous pouvez commencer les tests. Par d\u00e9faut, tous les tickets de type \u00ab\u00a0Test Case Execution\u00a0\u00bb et \u00ab\u00a0Test Run\u00a0\u00bb ont le statut \u00ab\u00a0No Run\u00a0\u00bb.<\/p>\n<h3>Comment passer d&#8217;un test \u00e0 un autre<\/h3>\n<p>Lorsque vous travaillez avec un ensemble de tests, il y a deux fa\u00e7ons de passer d&#8217;un test \u00e0 un autre\u00a0:<\/p>\n<ol>\n<li>Modifier manuellement le statut du test sur la page de la liste des tickets. <\/li>\n<li>Ouvrir un test et passer au test suivant non termin\u00e9. Une fen\u00eatre contextuelle vous sugg\u00e8re le prochain test \u00e0 ex\u00e9cuter.<br \/>\n    Les action suivantes peuvent \u00eatre automatis\u00e9es :<\/p>\n<ul>\n<li> La v\u00e9rification de l&#8217;existence de tests ayant le statut \u00ab\u00a0No Run\u00a0\u00bb et appartenant au m\u00eame Test Run.<\/li>\n<li> L&#8217;affichage d&#8217;un message avec l&#8217;URL du prochain test disponible (le cas \u00e9ch\u00e9ant).\n<p>    <a href=\"https:\/\/resources.jetbrains.com\/storage\/products\/blog\/wp-content\/uploads\/done3s720.gif\" rel=\"attachment wp-att-6366 noopener\" target=\"_blank\"><img decoding=\"async\" src=\"https:\/\/resources.jetbrains.com\/storage\/products\/blog\/wp-content\/uploads\/done3s720.gif\" alt=\"ApplyingCommandForSubsystem\"  \/><\/a><\/li>\n<\/ul>\n<p> Pour ce faire, utilisez le code ci-dessous.<\/p>\n<details>\n<summary>\n        \u00c9tendre le bloc de code<br \/>\n    <\/summary>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-title=\"\">\n action: function(ctx) {\n  var issue = ctx.issue;\n  if (!issue.links[&#039;subtask of&#039;].isEmpty) {\n              var parent = issue.links[&#039;subtask of&#039;].first();\n              var TestRunList = parent.links[ctx.Subtask.outward];\n              var resultSet = null;\n              var isPassing = true;\n              TestRunList.forEach(function(v) {\n                if (v.Status.name == ctx.Status.Failed.name) {\n                  isPassing = false;\n                } else if ((v.Status.name == ctx.Status.InProgress.name) &amp;&amp; (v.id !== issue.id)) {\n                  resultSet = v;\n                }\n              });\n              if (resultSet) {\n                var otherIssueLink = &#039;<a href=\"&#039; + resultSet.url + &#039;\"> &#039; + resultSet.id + &#039;<\/a>&#039;;\n                var message = &#039;Switch to next open test in current Test Run&#039; + otherIssueLink + &#039;.&#039;;\n                workflow.message(message);\n    }\n}\n}\n<\/pre>\n<p>\n<\/details>\n<\/ol>\n<h2>Statuts des tests <\/h2>\n<p><a name=\"ref2\"><\/a><\/p>\n<p>En passant d&#8217;un test \u00e0 un autre, vous pouvez soit attribuer au test le statut \u00ab\u00a0Passed\u00a0\u00bb (R\u00e9ussi) ou \u00ab\u00a0Failed\u00a0\u00bb (\u00c9chou\u00e9) si un bug a \u00e9t\u00e9 identifi\u00e9 pendant l&#8217;ex\u00e9cution du cas de test. En fonction des param\u00e8tres <a href=\"#ref1\">YouTrack<\/a> initialement configur\u00e9s pour ce projet, il existe plusieurs statuts de Test Run pr\u00e9d\u00e9finis :<\/p>\n<ul>\n<li>\u00ab\u00a0Failing\u00a0\u00bb : au moins un des tests associ\u00e9s a le statut \u00ab\u00a0No run\u00a0\u00bb et au moins un des tests associ\u00e9s a le statut \u00ab\u00a0Failed\u00a0\u00bb.<\/li>\n<li>\u00ab\u00a0Passing\u00a0\u00bb : au moins un des tests associ\u00e9s a le statut \u00ab\u00a0No run\u00a0\u00bb et aucun test associ\u00e9 n&#8217;a le statut \u00ab\u00a0Failed\u00a0\u00bb.<\/li>\n<li>\u00ab\u00a0Failed\u00a0\u00bb\u00a0: aucun test associ\u00e9 n&#8217;a le statut \u00ab\u00a0No Run\u00a0\u00bb et au moins un des tests associ\u00e9s a le statut \u00ab\u00a0Failed\u00a0\u00bb.<\/li>\n<li>\u00ab\u00a0Passed\u00a0\u00bb : aucun test associ\u00e9 n&#8217;a le statut \u00ab\u00a0No Run\u00a0\u00bb ou \u00ab\u00a0Failed\u00a0\u00bb.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/resources.jetbrains.com\/storage\/products\/blog\/wp-content\/uploads\/done2s720.gif\" alt=\"\" \/><\/p>\n<p>Ces statuts aident l&#8217;\u00e9quipe d&#8217;assurance qualit\u00e9 \u00e0 suivre la progression des tests tout au long du cycle de tests. Il est important de noter que le statut des s\u00e9ries de tests d\u00e9pend uniquement des tests associ\u00e9s et ne doit pas \u00eatre modifi\u00e9 manuellement. Le processus de d\u00e9termination des statuts de Test Run est impl\u00e9ment\u00e9 \u00e0 l&#8217;aide du workflow des <a href=\"https:\/\/www.jetbrains.com\/help\/youtrack\/standalone\/state-machine-per-issue-type.html#state-machine-per-issue-type2\" target=\"_blank\" rel=\"noopener\">machines d&#8217;\u00e9tat par type de ticket<\/a>. Le bloc de code pour le passage d&#8217;un test \u00e0 un autre est \u00e9galement int\u00e9gr\u00e9 dans le workflow.<\/p>\n<details>\n<summary>\n        \u00c9tendre le bloc de code<br \/>\n    <\/summary>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-title=\"\">\n\nvar entities = require(&#039;@jetbrains\/youtrack-scripting-api\/entities&#039;);\nvar workflow = require(&#039;@jetbrains\/youtrack-scripting-api\/workflow&#039;);\n\nexports.rule = entities.Issue.stateMachine({\n  title: &#039;status-management&#039;,\n  stateFieldName: &#039;Status&#039;,\n  typeFieldName: &#039;Type&#039;,\n  defaultMachine: {\n    &#039;No Run&#039;: {\n      initial: true,\n      transitions: {\n        &#039;Failed&#039;: {\n          targetState: &#039;Failed&#039;,\n          action: function(ctx) {\n            var issue = ctx.issue;\n            if (!issue.links[&#039;subtask of&#039;].isEmpty) {\n              var parent = issue.links[&#039;subtask of&#039;].first();\n              var TestRunList = parent.links[ctx.Subtask.outward];\n              var resultSet = null;\n              var isPassing = true;\n              TestRunList.forEach(function(v) {\n                if (v.Status.name == ctx.Status.Failed.name) {\n                  isPassing = false;\n                } else if ((v.Status.name == ctx.Status.InProgress.name) &amp;&amp; (v.id !== issue.id)) {\n                  resultSet = v;\n                }\n              });\n              if (resultSet) {\n                var otherIssueLink = &#039;<a href=\"&#039; + resultSet.url + &#039;\"> &#039; + resultSet.id + &#039;<\/a>&#039;;\n                var message = &#039;Switch to next open test in current Test Run&#039; + otherIssueLink + &#039;.&#039;;\n                workflow.message(message);\n                \/\/ Updating Test Run Status \n                parent.fields[\"Status\"] = ctx.Status.Failing;\n              } else {\n                parent.fields[\"Status\"] = ctx.Status.Failed;\n              }\n            }\n          }\n        },\n        &#039;Passed&#039;: {\n          guard: function(ctx) {\n            var issue = ctx.issue;\n            return !issue.isChanged(&#039;project&#039;) &amp;&amp; !issue.becomesReported &amp;&amp; issue.isReported &amp;&amp; (issue.Type.name == ctx.Type.TestExecution.name);\n          },\n          targetState: &#039;Passed&#039;,\n          action: function(ctx) {\n            var issue = ctx.issue;\n            if (!issue.links[&#039;subtask of&#039;].isEmpty) {\n              var parent = issue.links[&#039;subtask of&#039;].first();\n              var TestRunList = parent.links[ctx.Subtask.outward];\n              var resultSet = null;\n              var isPassing = true;\n              TestRunList.forEach(function(v) {\n                if (v.Status.name == ctx.Status.Failed.name) {\n                  isPassing = false;\n                } else if ((v.Status.name == ctx.Status.InProgress.name) &amp;&amp; (v.id !== issue.id)) {\n                  resultSet = v;\n                }\n              });\n              if (resultSet) {\n                var otherIssueLink = &#039;<a href=\"&#039; + resultSet.url + &#039;\"> &#039; + resultSet.id + &#039;<\/a>&#039;;\n                var message = &#039;Switch to next open test in current Test Run&#039; + otherIssueLink + &#039;.&#039;;\n                workflow.message(message);\n                parent.fields[\"Status\"] = (isPassing) ? ctx.Status.Passing : ctx.Status.Failing;\n              } else {\n                parent.fields[\"Status\"] = (isPassing) ? ctx.Status.Passed : ctx.Status.Failed;\n              }\n            }\n          }\n        }\n      }\n    },\n    Passed: {\n      transitions: {\n        &#039;Failed&#039;: {\n          guard: function(ctx) {\n            var issue = ctx.issue;\n            return !issue.isChanged(&#039;project&#039;) &amp;&amp; !issue.becomesReported &amp;&amp; issue.isReported &amp;&amp; (issue.Type.name == ctx.Type.TestExecution.name);\n          },\n          targetState: &#039;Failed&#039;,\n          action: function(ctx) {\n            var issue = ctx.issue;\n            if (!issue.links[&#039;subtask of&#039;].isEmpty) {\n             var parent = issue.links[&#039;subtask of&#039;].first();\n              var TestRunList = parent.links[ctx.Subtask.outward];\n              var resultSet = null;\n              TestRunList.forEach(function(v) {\n                if (v.Status.name == ctx.Status.Failed.name) {\n                } else if ((v.Status.name == ctx.Status.InProgress.name) &amp;&amp; (v.id !== issue.id)) {\n                  resultSet = v;\n                }\n              });\n              if (resultSet) {\n                var otherIssueLink = &#039;<a href=\"&#039; + resultSet.url + &#039;\"> &#039; + resultSet.id + &#039;<\/a>&#039;;\n                var message = &#039;Switch to next open test in current Test Run&#039; + otherIssueLink + &#039;.&#039;;\n                workflow.message(message);\n                parent.fields[\"Status\"] = ctx.Status.Failing;\n              } else {\n                parent.Status = ctx.Status.Failed;\n              }\n            }\n          }\n        },\n        &#039;No Run&#039;: {\n          guard: function(ctx) {\n            var issue = ctx.issue;\n            return !issue.isChanged(&#039;project&#039;) &amp;&amp; !issue.becomesReported &amp;&amp; issue.isReported &amp;&amp; (issue.Type.name == ctx.Type.TestExecution.name);\n          },\n          targetState: &#039;No Run&#039;,\n          action: function(ctx) {\n            var issue = ctx.issue;\n            if (!issue.links[&#039;subtask of&#039;].isEmpty) {\n              var parent = issue.links[&#039;subtask of&#039;].first();\n              var TestRunList = parent.links[ctx.Subtask.outward];\n              var ActiveTestRun = false;\n              var isPassing = true;\n              TestRunList.forEach(function(v) {\n                if (v.Status.name == ctx.Status.Failed.name) {\n                  isPassing = false;\n                  ActiveTestRun = true;\n                } else if ((v.Status.name == ctx.Status.Passed.name) &amp;&amp; (v.id !== issue.id)) {\n                  ActiveTestRun = true;\n                }\n              });\n              if (ActiveTestRun) {\n                parent.fields[\"Status\"] = (isPassing) ? ctx.Status.Passing : ctx.Status.Failing;\n              } else parent.fields[\"Status\"] = ctx.Status.InProgress;\n            }\n          }\n        }\n      }\n    },\n    Failed: {\n      transitions: {\n        &#039;Passed&#039;: {\n          guard: function(ctx) {\n            var issue = ctx.issue;\n            return !issue.isChanged(&#039;project&#039;) &amp;&amp; !issue.becomesReported &amp;&amp; issue.isReported &amp;&amp; (issue.Type.name == ctx.Type.TestExecution.name);\n          },\n          targetState: &#039;Passed&#039;,\n          action: function(ctx) {\n            var issue = ctx.issue;\n            if (!issue.links[&#039;subtask of&#039;].isEmpty) {\n              var parent = issue.links[&#039;subtask of&#039;].first();\n              var TestRunList = parent.links[ctx.Subtask.outward];\n              var resultSet = null;\n              var isPassing = true;\n              TestRunList.forEach(function(v) {\n                if ((v.Status.name == ctx.Status.Failed.name) &amp;&amp; (v.id !== issue.id)) {\n                  isPassing = false;\n                } else if ((v.Status.name == ctx.Status.InProgress.name) &amp;&amp; (v.id !== issue.id)) {\n                  resultSet = v;\n                }\n              });\n              if (resultSet) {\n                var otherIssueLink = &#039;<a href=\"&#039; + resultSet.url + &#039;\"> &#039; + resultSet.id + &#039;<\/a>&#039;;\n                var message = &#039;Switch to next open test in current Test Run&#039; + otherIssueLink + &#039;.&#039;;\n                workflow.message(message);\n\n                parent.fields[\"Status\"] = (isPassing) ? ctx.Status.Passing : ctx.Status.Failing;\n              } else {\n                parent.fields[\"Status\"] = (isPassing) ? ctx.Status.Passed : ctx.Status.Failed;\n              }\n            }\n          }\n        },\n        &#039;No Run&#039;: {\n          guard: function(ctx) {\n            var issue = ctx.issue;\n            return !issue.isChanged(&#039;project&#039;) &amp;&amp; !issue.becomesReported &amp;&amp; issue.isReported &amp;&amp; (issue.Type.name == ctx.Type.TestExecution.name);\n          },\n          targetState: &#039;No Run&#039;,\n          action: function(ctx) {\n            var issue = ctx.issue;\n            if (!issue.links[&#039;subtask of&#039;].isEmpty) {\n              var parent = issue.links[&#039;subtask of&#039;].first();\n              var TestRunList = parent.links[ctx.Subtask.outward];\n              var ActiveTestRun = false;\n              var isPassing = true;\n              TestRunList.forEach(function(v) {\n                if ((v.Status.name == ctx.Status.Failed.name) &amp;&amp; (v.id !== issue.id)) {\n                  isPassing = false;\n                  ActiveTestRun = true;\n                } else if ((v.Status.name == ctx.Status.Passed.name) &amp;&amp; (v.id !== issue.id)) {\n                  ActiveTestRun = true;\n                }\n              });\n              if (ActiveTestRun) {\n                parent.fields[\"Status\"] = (isPassing) ? ctx.Status.Passing : ctx.Status.Failing;\n              } else parent.fields[\"Status\"] = ctx.Status.InProgress;\n            }\n          }\n        }\n      }\n    }\n  },\n  alternativeMachines: {\n    &#039;Test Run&#039;: {\n      &#039;No Run&#039;: {\n        initial: true,\n        transitions: {\n          &#039;Failing&#039;: {\n            targetState: &#039;Failing&#039;,\n            action: function(ctx) {\n           \/* Add actions. *\/\n            }\n          },\n          &#039;Failed&#039;: {\n            targetState: &#039;Failed&#039;,\n            action: function(ctx) {\n         \/* Add actions. *\/\n            }\n          },\n          &#039;Passing&#039;: {\n            targetState: &#039;Passing&#039;,\n            action: function(ctx) {\n          \/* Add actions. *\/\n            }\n          },\n          &#039;Passed&#039;: {\n            targetState: &#039;Passed&#039;,\n            action: function(ctx) {\n           \/* Add actions. *\/\n            }\n          }\n        }\n      },\n      Failing: {\n        transitions: {\n          &#039;Passing&#039;: {\n            targetState: &#039;Passing&#039;,\n            action: function(ctx) {\n           \/* Add actions . *\/\n            }\n          },\n          &#039;Passed&#039;: {\n            targetState: &#039;Passed&#039;,\n            action: function(ctx) {\n          \/* Add actions. *\/\n            }\n          },\n          &#039;Failed&#039;: {\n            targetState: &#039;Failed&#039;,\n            action: function(ctx) {\n           \/* Add actions. *\/\n            }\n          }\n        }\n      },\n      Passing: {\n        transitions: {\n          &#039;Failing&#039;: {\n            targetState: &#039;Passing&#039;,\n            action: function(ctx) {\n              workflow.check(false, workflow.i18n(&#039;Test Run has-read-only status which is defined based on assigned tests statuses&#039;));\n            }\n          },\n          &#039;Passed&#039;: {\n            targetState: &#039;Passed&#039;,\n            action: function(ctx) {\n           \/* Add actions. *\/\n            }\n          },\n          &#039;Failed&#039;: {\n            targetState: &#039;Failed&#039;,\n            action: function(ctx) {\n           \/* Add actions. *\/\n            }\n          }\n        }\n      },\n      Failed: {\n        transitions: {\n          &#039;Passing&#039;: {\n            targetState: &#039;Passing&#039;,\n            action: function(ctx) {\n           \/* Add actions.\n *\/\n            }\n          },\n          &#039;Passed&#039;: {\n            targetState: &#039;Passed&#039;,\n            action: function(ctx) {\n           \/* Add actions. *\/\n            }\n          },\n          &#039;Failing&#039;: {\n            targetState: &#039;Failed&#039;,\n            action: function(ctx) {\n           \/* Add actions. *\/\n            }\n          }\n        }\n      },\n      Passed: {\n        transitions: {\n          &#039;Passing&#039;: {\n            targetState: &#039;Passing&#039;,\n            action: function(ctx) {\n           \/* Add actions. *\/\n            }\n          },\n          &#039;Failed&#039;: {\n            targetState: &#039;Passed&#039;,\n            action: function(ctx) {\n          \/* Add actions. *\/\n            },\n          },\n          &#039;Failing&#039;: {\n            targetState: &#039;Failed&#039;,\n            action: function(ctx) {\n           \/* Add actions. *\/\n            }\n          }\n        }\n      }\n    }\n  },\n  requirements: {\n    Assignee: {\n      type: entities.User.fieldType\n    },\n    Status: {\n      type: entities.EnumField.fieldType,\n      InProgress: {\n        name: &#039;No Run&#039;\n      },\n      Failing: {\n        name: &#039;Failing&#039;\n      },\n      Passing: {\n        name: &#039;Passing&#039;\n      },\n      Passed: {\n        name: &#039;Passed&#039;\n      },\n      Failed: {\n        name: &#039;Failed&#039;\n      },\n    },\n    Type: {\n      type: entities.EnumField.fieldType,\n      TestRun: {\n        name: \"Test Run\"\n      },\n      TestExecution: {\n        name: \"Test Case Execution\"\n      }\n    },\n    Subtask: {\n      type: entities.IssueLinkPrototype,\n      name: &#039;Subtask&#039;,\n      inward: &#039;subtask of&#039;,\n      outward: &#039;parent for&#039;\n    },\n  }\n});\n <\/pre>\n<p>\n <\/details>\n<h1>Statistiques des tests<\/h1>\n<p>Vous pouvez \u00e9galement \u00eatre int\u00e9ress\u00e9 par les statistiques cl\u00e9s du cycle de test. Pour les besoins de cette d\u00e9monstration, nous avons int\u00e9gr\u00e9 les indicateurs suivants :<\/p>\n<ul>\n<li>Nombre total de tests affect\u00e9s \u00e0 un Test Run sp\u00e9cifique.<\/li>\n<li>Nombre de tests avec le statut \u00ab\u00a0Passed\u00a0\u00bb.<\/li>\n<li>Nombre de tests avec le statut \u00ab\u00a0Failed\u00a0\u00bb (\u00c9chec).<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/resources.jetbrains.com\/storage\/products\/blog\/wp-content\/uploads\/done5s720.gif\" alt=\"\" \/><br \/>\nGr\u00e2ce au code ci-dessous, toutes les mesures sont mises \u00e0 jour en cas de modification de l&#8217;un des \u00e9l\u00e9ments suivants : changement de statut du test, affectation d&#8217;un nouveau test au Test Run et suppression d&#8217;un test du Test Run.<\/p>\n<details>\n<summary>\n        \u00c9tendre le bloc de code<br \/>\n    <\/summary>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-title=\"\">\n  exports.calculateStatuses = function(parent) {\n  var totalTR = 0;\n  var totalFailed = 0;\n  var totalPassed = 0;\n  if (!parent.links[&#039;parent for&#039;]) {\n    return;\n  } else {\n    parent.links[&#039;parent for&#039;].forEach(function(tr) {\n      totalTR++;\n      if (tr.Status.name == &#039;Passed&#039;) {\n        totalFailed++;\n      }\n      if (tr.Status.name == &#039;Failed&#039;) {\n        totalPassed++;\n      }\n    });\n    parent.fields[&#039;Total number of test cases&#039;] = totalTR;\n    parent.fields[&#039;Number of passed test cases&#039;] = totalPassed;\n    parent.fields[&#039;Number of failed test cases&#039;] = totalFailed;\n    return true;\n  }\n};\nexports.resetStatuses = function(testRun, testRunCopy) {\n   testRunCopy.fields[&#039;Total number of test cases&#039;] = testRun.fields[&#039;Total number of test cases&#039;];\n   testRunCopy.fields[&#039;Number of passed test cases&#039;] = 0;\n   testRunCopy.fields[&#039;Number of failed test cases&#039;] = 0;\n  return true;\n};\n<\/pre>\n<p>\n<\/details>\n<p>Dans notre cas, ce code est d\u00e9clench\u00e9 par plusieurs r\u00e8gles de workflow, telles que \u00ab\u00a0Update stats when links are adjusted\u00a0\u00bb (Mettre \u00e0 jour les statistiques lorsque les liens sont ajust\u00e9s), \u00ab\u00a0Switch to the next test case\u00a0\u00bb (Passer au cas de test suivant) entre autres. Si vous souhaitez adopter un ensemble de mesures qui r\u00e9pondent \u00e0 vos besoins sp\u00e9cifiques, vous pouvez ajouter les champs personnalis\u00e9s requis et ajuster votre logique de workflow.<\/p>\n<h2>Fonctionnalit\u00e9s de suivi de tickets<\/h2>\n<p>Vous pouvez cr\u00e9er une t\u00e2che distincte pour traiter un bug identifi\u00e9 pour un test \u00e9chou\u00e9 et l&#8217;associer \u00e0 un ticket qui identifie l&#8217;ex\u00e9cution du cas de test correspondant. Vous pouvez soit associer les \u00e9checs de tests aux bugs correspondants en utilisant un type de lien de ticket personnalis\u00e9, soit utiliser un champ de texte personnalis\u00e9 contenant une r\u00e9f\u00e9rence au bug. Il peut \u00eatre plus facile d&#8217;opter pour un projet YouTrack s\u00e9par\u00e9 afin d&#8217;effectuer le suivi des bugs.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/TMS7.png\" alt=\"\" \/><\/p>\n<h2>Am\u00e9liorations possibles<\/h2>\n<p>Vous pouvez \u00e9tendre les fonctionnalit\u00e9s de YouTrack pour r\u00e9pondre \u00e0 des crit\u00e8res ou exigences suppl\u00e9mentaires. Plusieurs options sont possibles.<\/p>\n<h3>Cloner un Test Run existant<\/h3>\n<p>Il est parfois pr\u00e9f\u00e9rable d\u2019avoir un nouveau Test Run similaire \u00e0 un Test Run existant, avec seulement quelques petites modifications (par exemple, un changement de la version attribu\u00e9e). Nous proposons l&#8217;option \u00ab\u00a0Create Test Run copy\u00a0\u00bb pr\u00e9cis\u00e9ment pour de tels cas. Cet \u00e9l\u00e9ment du menu n&#8217;est disponible que pour les tickets de type \u00ab\u00a0Test Run\u00a0\u00bb et d\u00e9clenche les actions suivantes\u00a0:<\/p>\n<ul>\n<li>Cr\u00e9ation d&#8217;une copie du Test Run et de copies des ex\u00e9cutions de cas de tests qui lui sont attribu\u00e9es.<\/li>\n<li>Tous les copies d&#8217;ex\u00e9cutions de cas de tests sont affect\u00e9es au nouveau Test Run en utilisant le type de lien \u00ab parent-child \u00bb. Ces copies seront attribu\u00e9es aux cas de test originaux avec le type de lien de ticket \u00ab\u00a0Execution\u00a0\u00bb afin de maintenir la tra\u00e7abilit\u00e9.<\/li>\n<li>Les statuts et statistiques ne seront pas inclus dans le nouveau ticket. <\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/resources.jetbrains.com\/storage\/products\/blog\/wp-content\/uploads\/done8s720.gif\" alt=\"\" \/><\/p>\n<p>La logique ci-dessus est impl\u00e9ment\u00e9e en utilisant la r\u00e8gle d&#8217;action \u00ab\u00a0Create Test Run copy\u00a0\u00bb.<\/p>\n<details>\n<summary>\n        \u00c9tendre le bloc de code<br \/>\n    <\/summary>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-title=\"\">\nvar workflow = require(&#039;@jetbrains\/youtrack-scripting-api\/workflow&#039;);\nvar entities = require(&#039;@jetbrains\/youtrack-scripting-api\/entities&#039;);\nvar utils = require(&#039;..\/calculate-tms-stats\/utils&#039;);\n\nexports.rule = entities.Issue.action({\n  title: &#039;Create Test Run copy&#039;,\n  command: &#039;Test Run Creation&#039;,\n  guard: function(ctx) {\n    return ctx.issue.isReported &amp;&amp; (ctx.issue.Type.name == ctx.Type.TestRun.name);\n  },\n  action: function(ctx) {\n    var issue = ctx.issue;\n    var TestRunCopy = issue.copy(issue.project);\n    TestRunCopy.Status = ctx.Status.InProgress; \n    var oldTestList = issue.links[ctx.Subtask.outward];\n    oldTestList.forEach(function(v) {\n      var newTest = v.copy(v.project);\n      newTest.Status = ctx.Status.InProgress;\n      newTest.links[ctx.Subtask.inward].delete(issue);\n      newTest.links[ctx.Subtask.inward].add(TestRunCopy);\n    });\n    utils.resetStatuses(issue, TestRunCopy); \n    var newTestRunLink = &#039;<a href=\"&#039; + TestRunCopy.url + &#039;\"> &#039; + TestRunCopy.id + &#039;<\/a>&#039;;\n    var message = &#039;New Test Run has been created &#039; + newTestRunLink + &#039;.&#039;;\n    workflow.message(message);\n  },\n  requirements: {\n    Execution: {\n      type: entities.IssueLinkPrototype,\n      name: &#039;Execution&#039;,\n      inward: &#039;Execution&#039;,\n      outward: &#039;Assigned Test case or test suite&#039;\n    },\n    Subtask: {\n      type: entities.IssueLinkPrototype,\n      name: &#039;Subtask&#039;,\n      inward: &#039;subtask of&#039;,\n      outward: &#039;parent for&#039;\n    },\n    Type: {\n      type: entities.EnumField.fieldType,\n      TestRun: {\n        name: \"Test Run\"\n      },\n    },\n    Status: {\n      type: entities.EnumField.fieldType,\n      InProgress: {\n        name: &#039;No Run&#039;\n      },\n    }\n  }\n});\n <\/pre>\n<p>\n <\/details>\n<h2>Limiter les actions des utilisateurs<\/h2>\n<p>Afin d&#8217;\u00e9viter les erreurs potentielles avec les sc\u00e9narios de tests (par exemple en utilisant les mauvais types de tickets), vous pouvez limiter les actions des utilisateurs. Par exemple, vous pouvez impl\u00e9menter des actions pour vous assurer que les utilisateurs associent les cas de test aux Test Runs. Le fait de lier un Test Run \u00e0 un ticket, permet de v\u00e9rifier si le type de ticket associ\u00e9 est \u00ab\u00a0Test Case\u00a0\u00bb ou \u00ab\u00a0Test Suite\u00a0\u00bb. S&#8217;il ne s&#8217;agit d&#8217;aucun des deux, l&#8217;action envoie alors un avertissement qui emp\u00eache l&#8217;utilisateur de poursuivre.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/resources.jetbrains.com\/storage\/products\/blog\/wp-content\/uploads\/done9.720.gif\" alt=\"\" \/><\/p>\n<p>Le bloc de code suivant peut \u00eatre ajout\u00e9 au workflow \u00ab\u00a0Populate Test Run\u00a0\u00bb (Remplir la s\u00e9rie de tests).<\/p>\n<details>\n<summary>\n        \u00c9tendre le bloc de code<br \/>\n    <\/summary>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-title=\"\">\n var message = &#039;<a href=\"&#039; + TestCase.url + &#039;\"> &#039; + TestCase.id + &#039;<\/a>&#039;;\n      workflow.check((TestCase.Type.name == ctx.Type.TestCase.name) || (TestCase.Type.name == ctx.Type.TestSuite.name), workflow.i18n(&#039;\\&#039;Test Run\\&#039; can be linked to \\&#039;Test Case\\&#039; and \\&#039;Test Suite\\&#039; only, but {0} has \\&#039;{1}\\&#039; type!&#039;, message, TestCase.Type.name));\n    <\/pre>\n<p>\n    <\/details>\n<p>Comme mentionn\u00e9 <a href=\"#ref2\">ci-dessus<\/a>, le statut de Test Run doit \u00eatre en lecture seule, car il d\u00e9pend de la progression des ex\u00e9cutions de tests. Cela peut \u00eatre r\u00e9alis\u00e9 de mani\u00e8re simple, en incluant un bloc de code qui limite les changements de statuts manuels pour les tickets de type \u00ab\u00a0Test Run\u00a0\u00bb.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/done10s720.gif\" alt=\"\" \/><br \/>\nPar exemple, la section transitions pour le type de ticket Test Run dans le workflow status-mangement peut \u00eatre ajust\u00e9e comme suit :<\/p>\n<details>\n<summary>\n        \u00c9tendre le bloc de code<br \/>\n    <\/summary>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-title=\"\">\n   &#039;Failing&#039;: {\n            targetState: &#039;Failing&#039;,\n            action: function(ctx) {\n              workflow.check(false, workflow.i18n(&#039;Test run has read-only status which is defined based on assigned tests statuses&#039;));\n            }\n          },\n          ...\n        }\n<\/pre>\n<p>\n<\/details>\n<h2>G\u00e9n\u00e9ration de rapports et tra\u00e7abilit\u00e9<\/h2>\n<h3>Cr\u00e9ation de rapports<\/h3>\n<p>Une fois le cycle de tests termin\u00e9, vous voudrez peut-\u00eatre analyser les r\u00e9sultats. La fonctionnalit\u00e9 de rapport dans YouTrack peut \u00eatre utilis\u00e9e \u00e0 cette fin. Vous pouvez s\u00e9lectionner le type de rapport, qui affichera les informations cl\u00e9s relatives \u00e0 la proc\u00e9dure de gestion des tests. Pour les besoins de cette d\u00e9monstration, nous avons ajout\u00e9 deux rapports au tableau de bord\u00a0:<\/p>\n<ul>\n<li>\n<em><b>Rapport de flux cumul\u00e9 avec filtrage par champ \u00ab\u00a0version\u00a0\u00bb.<\/b><\/em> Ce type de rapport d&#8217;\u00e9tat fait r\u00e9f\u00e9rence \u00e0 une version sp\u00e9cifique du produit. Il pr\u00e9sente des mesures cl\u00e9s, comme le nombre de tests avec les statuts \u00ab\u00a0Passed\u00a0\u00bb, \u00ab\u00a0Failed\u00a0\u00bb et \u00ab\u00a0No Run\u00a0\u00bb, sur une chronologie. Afin d&#8217;afficher les donn\u00e9es inter-versions, vous devez cr\u00e9er un rapport pour chaque version. Nous vous recommandons d&#8217;ajouter tous les rapports au tableau de bord afin de pouvoir travailler avec toutes les donn\u00e9es en un seul endroit.<\/p>\n<h3>Configuration du rapport :<\/h3>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/TMS11.png\" rel=\"attachment wp-att-6366\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/TMS11.png\" alt=\"ApplyingCommandForSubsystem\" \/><\/a><\/p>\n<h3>R\u00e9sultats du rapport :<\/h3>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/TMS12.png\" rel=\"attachment wp-att-6366\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/TMS12.png\" alt=\"ApplyingCommandForSubsystem\" \/><\/a><\/p>\n<\/li>\n<li><em><b>Rapport sur la distribution des tickets.<\/b><\/em> Ce rapport est un instantan\u00e9 qui comprend des mesures cl\u00e9s (telles que le nombre de s\u00e9ries de tests effectu\u00e9es pour chaque statut) pour plusieurs versions du produit. Pour cette d\u00e9monstration, nous avons inclus un rapport de r\u00e9sultats qui peut vous aider \u00e0 comparer les versions entre elles et \u00e0 analyser leur stabilit\u00e9.<br \/>\n<h3>Configuration du rapport :<\/h3>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/TMS13.png\" rel=\"attachment wp-att-6366\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/TMS13.png\" alt=\"ApplyingCommandForSubsystem\" \/><\/a><\/p>\n<h3>R\u00e9sultats du rapport :<\/h3>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/re_res_cut.png\" rel=\"attachment wp-att-6366\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/re_res_cut.png\" alt=\"ApplyingCommandForSubsystem\" \/><\/a>\n <\/li>\n<\/ul>\n<h2>Tra\u00e7abilit\u00e9 <\/h2>\n<p>Comme YouTrack stocke les informations cl\u00e9s du cycle de tests pour chaque ticket avec le type \u00ab\u00a0Test Execution\u00a0\u00bb, vous pouvez toujours acc\u00e9der \u00e0 l&#8217;historique des tests et identifier les bugs associ\u00e9s.<br \/>\nSi vous avez un cas test, vous pouvez vous r\u00e9f\u00e9rer \u00e0 toutes les ex\u00e9cutions de tests qui l&#8217;impliquent.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/TMS15.png\" alt=\"\" \/><\/p>\n<p>Avec l&#8217;ex\u00e9cution de cas de tests, vous pouvez vous r\u00e9f\u00e9rer \u00e0 un Test Run.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/TMS16.png\" alt=\"\" \/><\/p>\n<p>Si l&#8217;ex\u00e9cution d&#8217;un cas de test \u00e9choue, vous pouvez toujours vous r\u00e9f\u00e9rer \u00e0 la liste des bugs associ\u00e9s.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2020\/09\/TMS17.png\" alt=\"\" \/><\/p>\n<p>Pour plus de d\u00e9tails sur les workflows d\u00e9crits dans cet article ou pour discuter d&#8217;autres sujets li\u00e9s aux workflows, n&#8217;h\u00e9sitez pas \u00e0 rejoindre notre communaut\u00e9 <a href=\"http:\/\/youtrack-community.herokuapp.com\/\" target=\"_blank\" rel=\"noopener\"> YouTrack Workflow <\/a> sur Slack.<\/p>\n<p><em>Auteur de l&#8217;article original en anglais : <a href=\"https:\/\/blog.jetbrains.com\/author\/leonid-zalog-jetbrains-com\/\" target=\"_blank\" rel=\"noopener noreferrer\">Leonid Zalog<\/a><\/em><\/p>\n","protected":false},"author":813,"featured_media":83084,"comment_status":"closed","ping_status":"closed","template":"","categories":[4129],"tags":[],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/youtrack\/90259"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/youtrack"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/types\/youtrack"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/users\/813"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/comments?post=90259"}],"version-history":[{"count":1,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/youtrack\/90259\/revisions"}],"predecessor-version":[{"id":90261,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/youtrack\/90259\/revisions\/90261"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/media\/83084"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/media?parent=90259"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/categories?post=90259"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/tags?post=90259"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/cross-post-tag?post=90259"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}