threadable/qality-plus

Laravel and PHPUnit integration for publishing automated test results to QAlity Plus.

Maintainers

Package info

github.com/threadable/qality-plus

pkg:composer/threadable/qality-plus

Transparency log

Statistics

Installs: 7

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-08-13 18:41 UTC

This package is auto-updated.

Last update: 2026-08-26 10:33:56 UTC


README

This package records Laravel, PHPUnit, and Pest test results and publishes them to QAlity Plus and Jira from your CI/CD pipeline.

Installation

composer require threadable/qality-plus

If your organization distributes the package through Private Packagist, see Private Packagist setup before running this command.

The package is auto-discovered by Laravel. Publish the configuration only when you need to change a default:

php artisan vendor:publish --tag=qality-config

Setup

Register the PHPUnit extension in phpunit.xml:

<extensions>
    <bootstrap class="Threadable\QalityPlus\PhpUnit\QalityPlusExtension">
        <parameter name="directory" value="storage/qality"/>
        <parameter name="schema_version" value="1"/>
    </bootstrap>
</extensions>

Add these CI/CD variables:

QALITY_PLUS_API_TOKEN=...
QALITY_PLUS_PROJECT_ID=...

QALITY_JIRA_BASE_URL=https://example.atlassian.net
QALITY_JIRA_EMAIL=ci@example.com
QALITY_JIRA_API_TOKEN=...

# Jira project containing the QAlity test cases
QALITY_JIRA_PROJECT_KEY=QA

The Jira project key is used to find existing QAlity test cases by name. The default Jira test issue type is QAlity Test; override it with QALITY_JIRA_TEST_ISSUE_TYPE when necessary.

For alternative authentication, explicit mappings, data providers, or other configuration options, see Advanced configuration.

Map tests to QAlity

To use an existing QAlity test case, put the attribute on the individual test method:

use Threadable\QalityPlus\PhpUnit\QalityTestCase;

final class CheckoutTest extends TestCase
{
    #[QalityTestCase('QA-123', requirementIssueKey: 'REQ-42')]
    public function test_checkout_can_be_completed(): void
    {
        // ...
    }
}

To create a missing case with a friendly name, provide only a name:

#[QalityTestCase(name: 'Customer can complete checkout')]
public function test_checkout_can_be_completed(): void
{
    // ...
}

If only a requirement is supplied, the fully qualified PHPUnit class and method name or Pest description is used as the QAlity test-case name:

#[QalityTestCase(requirementIssueKey: 'NDC-123')]
public function test_user_can_reset_their_password(): void
{
    // ...
}

When no name is provided, the package uses the fully qualified PHPUnit class and method name, or the Pest test description. If an issue key is already available, the case is treated as existing and its name is not changed.

requirementIssueKey is the source of truth for the Jira issue linked to that test. It overrides the --work-item value. When it is omitted, the branch work item is used as the fallback. This applies to both newly created and already existing QAlity test cases. linkType and linkDirection can override the configured defaults for an individual test.

CI/CD commands

Run the tests, then create or find the QAlity test cases on feature branches:

php artisan test
php artisan qality:create-test-cases --branch feature/PROJ-123-checkout

When the pipeline does not expose a branch name, provide the Jira work item directly. This skips branch detection and parsing:

php artisan qality:create-test-cases --work-item PROJ-123

On QA, UAT, and production deployments, run the tests and publish their executions:

php artisan test
php artisan qality:publish

Both commands use storage/qality by default. A different result file or directory can be supplied when needed. Use --dry-run to validate results without calling QAlity or Jira:

php artisan qality:create-test-cases --branch feature/PROJ-123-checkout --dry-run
php artisan qality:publish --dry-run

If an upstream request fails, inspect the Laravel application log (normally storage/logs/laravel.log) and search for qality-plus. Entries identify whether the failure occurred in QAlity Plus or Jira, the configured host and HTTP endpoint, the attempt number, response status, retry decision, and command stage. Timeout, DNS, and other connection failures are identified separately; HTTP failures include the returned status code. Request payloads and authentication tokens are not logged.

The mapping file is optional when QALITY_JIRA_PROJECT_KEY is configured. The create command first looks for an exact Jira test-case name in the configured project and creates a new case only when no matching case exists. It also reconciles the Jira link for cases found through the mapping file or name lookup. The publish command uses the same lookup when a result has no issue key. Therefore, a pipeline may discard .qality-test-map.json after each run when test names are stable and unique; Jira is searched again on the next run.

Name lookups are sent to Jira in batches, then compared against exact issue summaries locally. Only tests with no exact match are sent to the QAlity Plus import endpoint.

If QALITY_JIRA_PROJECT_KEY is not configured and the mapping file is absent, unmapped tests are sent to QAlity Plus for import on every run and may create duplicates. Also, --dry-run does not call Jira or QAlity, so its eligible count does not include name-based lookup results.

Branches are expected to use feature/KEY-123-description, hotfix/KEY-123-description, or bugfix/KEY-123-description. Use --branch for CI systems where the branch cannot be detected automatically. Use --work-item when the work item is already available separately; it takes precedence over --branch.

Workflow

Pipeline stage Command Result
Feature branch qality:create-test-cases Finds existing cases or creates missing cases and links each case to its annotated requirement, or to the branch work item when no requirement is annotated
QA, UAT, production qality:publish Creates a QAlity Test Cycle and publishes passed, failed, and skipped executions

Store QAlity and Jira credentials as secured CI/CD variables. The package does not require a particular CI/CD provider.

Newly created QAlity test cases receive the Jira label threadable-qality-plus by default. Set QALITY_JIRA_CREATED_TEST_LABEL= to disable the label.

Laravel Boost

This package includes Laravel Boost guidelines and a development skill. In a Laravel application, install Boost as a development dependency and run its installer to make the package guidance available to your AI coding agent:

composer require laravel/boost --dev
php artisan boost:install

Contributing

See CONTRIBUTING.md for development and pull-request guidelines. At minimum, install the dependencies and run the full quality check:

composer install
composer ci

Please include tests for behavior changes and open an issue before starting large changes.

Security issues should be reported privately as described in SECURITY.md.

License

This package is open-sourced software licensed under the MIT license.