Skip to content

Commit

Permalink
Added new config param and ability to set labels on issues.
Browse files Browse the repository at this point in the history
  • Loading branch information
ueslialmeida committed Nov 16, 2021
1 parent 599b62b commit adb369f
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 35 deletions.
29 changes: 16 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
jira-codeception-extension
=============================
# jira-codeception-extension

This package provides an extension for Codeception to create issues in Jira automatically when a test fails.

### How it works?

When you run a test and it fails the extension will connect with your Jira instance through the Jira API and create an issue containing the data generated by Codeception at the moment of the failure. The number of issues created will vary depending on the number of failed tests, if two tests failed then two separated issues will be created.

The issue will contain the following data:
- Test Name
- Failure Message
- Failed Step
- File Name

- Test Name
- Failure Message
- Failed Step
- File Name
- Stack Trace

### Configuration Example

This extension creates a Jira issue after a test failure. To use this extension a valid Jira configuration is required.
This extension creates a Jira issue after a test failure. To use this extension a valid Jira configuration is required.

- host: A Jira instance.
- user: A valid user that has permission to create issues in the specified project.
- token: A valid token for the specified user. The API will not accept the user password so a token is required. You can create a token in the user configuration panel, for more information follow the Jira official documentation [here](https://confluence.atlassian.com/cloud/api-tokens-938839638.html).
- projectKey: A valid Jira project key (e.g. TA, ZTE, ETC).
- issueType: Usually the issue is created as a Bug but you can change it for Task or another valid issue type available in your Jira instance.
- debugMode: In case you are creating tests or debugging tests you may not want to create issues (and I don't recommend it) so setting this config to true the extension will not create issues in production set it back to false.
- host: A Jira instance.
- user: A valid user that has permission to create issues in the specified project.
- token: A valid token for the specified user. The API will not accept the user password so a token is required. You can create a token in the user configuration panel, for more information follow the Jira official documentation [here](https://confluence.atlassian.com/cloud/api-tokens-938839638.html).
- projectKey: A valid Jira project key (e.g. TA, ZTE, ETC).
- issueType: Usually the issue is created as a Bug but you can change it for Task or another valid issue type available in your Jira instance.
- debugMode: In case you are creating tests or debugging tests you may not want to create issues (and I don't recommend it) so setting this config to true the extension will not create issues in production set it back to false.

Configuration 'codeception.yml' example:

Expand All @@ -36,4 +37,6 @@ Configuration 'codeception.yml' example:
token: Tg7womaGGFpn9EC16qD3L7T6
projectKey: JE
issueType: Bug
label:
- autotest_bug
debugMode: false
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@
"Codeception\\": "src"
}
},
"require": {},
"require": {}
}
56 changes: 35 additions & 21 deletions src/Extension/JiraExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
* token: Tg7womaGGFpn9EC16qD3L7T6
* projectKey: JE
* issueType: Bug
* label:
* - autotest_bug
* debugMode: false
*/
class JiraExtension extends \Codeception\Extension
Expand All @@ -39,6 +41,7 @@ class JiraExtension extends \Codeception\Extension
protected $projectKey;
protected $issueType;
protected $debug;
protected $label;

/**
* Issue fields.
Expand Down Expand Up @@ -67,7 +70,7 @@ public function _initialize()
if (!isset($this->config['user']) or empty($this->config['user'])) {
throw new ExtensionException($this, "Configuration for 'user' is missing.");
}

$this->user = $this->config['user'];

if (!isset($this->config['token']) or empty($this->config['token'])) {
Expand All @@ -88,6 +91,12 @@ public function _initialize()

$this->issueType = $this->config['issueType'];

if (!isset($this->config['label'])) {
throw new ExtensionException($this, "Configuration for 'label' is missing. You may leave it blank but it must be declared.");
}

$this->label = $this->config['label'];

if (!isset($this->config['debugMode'])) {
throw new ExtensionException($this, "Configuration for 'debug mode' is missing. Possible values are 'true' or 'false'.");
}
Expand All @@ -99,7 +108,8 @@ public function _initialize()
* This method is fired when the event 'step.after' occurs.
* @param \Codeception\Event\StepEvent $e
*/
public function afterStep(\Codeception\Event\StepEvent $e) {
public function afterStep(\Codeception\Event\StepEvent $e)
{
if ($e->getStep()->hasFailed()) {
$this->failedStep = $e->getStep()->toString(self::STRING_LIMIT);
}
Expand All @@ -109,22 +119,23 @@ public function afterStep(\Codeception\Event\StepEvent $e) {
* This method is fired when the event 'test.fail' occurs.
* @param \Codeception\Event\FailEvent $e
*/
public function testFailed(\Codeception\Event\FailEvent $e) {
public function testFailed(\Codeception\Event\FailEvent $e)
{
if (!$this->debug) {
$this->stackTrace = $e->getFail()->getTraceAsString();
$this->failureMessage = $e->getFail()->getMessage();
$this->fileName = $e->getTest()->getMetadata()->getFilename();
$this->testName = $e->getTest()->getMetadata()->getName();

$this->createIssue();
}
else {
echo("Debug mode is active, no issue will be created in Jira.\n\n");
} else {
echo ("Debug mode is active, no issue will be created in Jira.\n\n");
}
}

private function createIssue() {
echo("Creating issue in Jira...\n");
private function createIssue()
{
echo ("Creating issue on Jira...\n");

$jiraAPI = $this->host . '/rest/api/2/issue';

Expand All @@ -143,32 +154,35 @@ private function createIssue() {
curl_setopt($request, CURLOPT_POSTFIELDS, $issue);

$response = curl_exec($request);
echo("Jira response: $response \n\n");
echo ("Jira response: $response \n\n");
}

private function getIssueData() {
private function getIssueData()
{
$cleanFileName = $this->removeFilePath($this->fileName);

return [
'fields' => [
'project' => ['key' => "$this->projectKey"],
'summary' => $cleanFileName . ' : ' . $this->testName,
'description' => "
Test Name: $this->testName \n
Failure Message: $this->failureMessage \n
Failed Step: I $this->failedStep \n
File Name: $this->fileName \n
Stack Trace:\n $this->stackTrace",
'issuetype' => ['name' => $this->issueType],
'project' => ['key' => "$this->projectKey"],
'summary' => $cleanFileName . ' : ' . $this->testName,
'description' => "
Test Name: $this->testName \n
Failure Message: $this->failureMessage \n
Failed Step: I $this->failedStep \n
File Name: $this->fileName \n
Stack Trace:\n $this->stackTrace",
'issuetype' => ['name' => $this->issueType],
'labels' => $this->label,
]
];
}

private function removeFilePath($filePath) {
private function removeFilePath($filePath)
{
$pattern = "/[a-zA-Z\d]+\.[php]+/";
$path = explode('/', $filePath);
$fileName = implode(preg_grep($pattern, $path));

return $fileName;
}
}

0 comments on commit adb369f

Please sign in to comment.