Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Pyrameter Laravel Package

boundwize/pyrameter

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add to your Laravel project via Composer:

    composer require --dev boundwize/pyrameter
    

    Ensure PHPUnit is installed (phpunit/phpunit in require-dev).

  2. First Run Execute tests normally:

    vendor/bin/phpunit
    

    Pyrameter will automatically analyze your test suite and display a shape report.

  3. Initial Use Case

    • Identify Test Pyramid Shape: Check if your test suite follows the Test Pyramid principle (unit tests > integration > E2E).
    • Baseline Metrics: Note the initial "shape" (e.g., "Integration Mountain") and "result" (e.g., "Violated ⚠").
  4. Where to Look First

    • Test Grouping: Ensure tests are grouped logically (e.g., Unit/, Integration/, Feature/).
    • Pyrameter Output: Focus on the Shape: and Result: lines in the terminal. Example:
      Shape:  Unit Pyramid ✓
      Result: Compliant ✅
      
    • Configuration: Check phpunit.xml for custom test suite paths or exclusions.

Implementation Patterns

Workflow Integration

  1. CI/CD Pipeline Add Pyrameter to your CI workflow (e.g., GitHub Actions) to enforce test pyramid compliance:

    - name: Run PHPUnit with Pyrameter
      run: vendor/bin/phpunit --testdox-html=report.html
    

    Fail the build if the shape is "Violated" (customize via config).

  2. Test Suite Organization

    • Standardize Paths: Use consistent naming conventions:
      tests/
      ├── Unit/          # Unit tests (base of pyramid)
      ├── Integration/   # Integration tests (middle)
      └── Feature/       # E2E/Feature tests (apex)
      
    • Annotations: Tag tests with @group unit, @group integration, etc., for dynamic grouping.
  3. Dynamic Configuration Override default behavior in phpunit.xml:

    <phpunit>
        <extensions>
            <extension class="Boundwize\Pyrameter\Extension">
                <arguments>
                    <argument name="unitPath" value="tests/Unit"/>
                    <argument name="integrationPath" value="tests/Integration"/>
                    <argument name="e2ePath" value="tests/Feature"/>
                    <argument name="threshold">
                        <array>
                            <element><unit>70</unit></element>
                            <element><integration>20</integration></element>
                            <element><e2e>10</e2e></element>
                        </array>
                    </argument>
                </arguments>
            </extension>
        </extensions>
    </phpunit>
    
  4. Laravel-Specific Patterns

    • Artisan Commands: Extend Pyrameter with a custom Artisan command to visualize the pyramid:
      // app/Console/Commands/TestPyramidCommand.php
      use Boundwize\Pyrameter\Pyrameter;
      
      class TestPyramidCommand extends Command {
          protected $signature = 'test:pyramid';
          protected $description = 'Display test pyramid shape';
      
          public function handle(Pyrameter $pyrameter) {
              $shape = $pyrameter->analyze();
              $this->line($shape->toAsciiArt());
          }
      }
      
    • Service Provider: Bind Pyrameter to the container for dependency injection:
      // app/Providers/AppServiceProvider.php
      public function register() {
          $this->app->bind(Pyrameter::class, function () {
              return new Pyrameter(
                  config('pyrameter.unit_path'),
                  config('pyrameter.integration_path'),
                  config('pyrameter.e2e_path')
              );
          });
      }
      

Gotchas and Tips

Pitfalls

  1. False Positives/Negatives

    • Issue: Pyrameter may misclassify tests if paths overlap or are misconfigured.
    • Fix: Use explicit paths and avoid nested test directories (e.g., tests/Unit/User/ vs. tests/Unit/).
    • Debug: Run with --debug flag to see raw test classification:
      vendor/bin/phpunit --debug --extensions=Boundwize\Pyrameter\Extension
      
  2. Threshold Sensitivity

    • Issue: Default thresholds (e.g., 70% unit tests) may be too strict for large codebases.
    • Fix: Adjust thresholds in phpunit.xml or config. Example:
      <argument name="threshold">
          <array>
              <element><unit>50</unit></element>
              <element><integration>30</integration></element>
              <element><e2e>20</e2e></element>
          </array>
      </argument>
      
  3. Performance Overhead

    • Issue: Pyrameter adds minimal overhead (~1-2s for large suites), but may slow down CI.
    • Fix: Run Pyrameter in a separate job or cache results if using GitHub Actions.
  4. Test Naming Conflicts

    • Issue: Tests named similarly across layers (e.g., UserTest.php in Unit/ and Integration/) may cause confusion.
    • Fix: Use suffixes (e.g., UserUnitTest.php, UserIntegrationTest.php) or clear naming conventions.

Debugging

  1. Verbose Output Enable debug mode to see detailed classification:

    vendor/bin/phpunit -d pyrameter.debug=1
    

    Output will include:

    [Pyrameter] Classified 150 tests:
    - Unit: 105 (70%)
    - Integration: 30 (20%)
    - E2E: 15 (10%)
    
  2. Custom Exclusions Exclude specific tests or directories from analysis:

    <extension class="Boundwize\Pyrameter\Extension">
        <arguments>
            <argument name="excludedPaths" value="tests/Unit/SlowTests"/>
        </arguments>
    </extension>
    

Extension Points

  1. Custom Shapes Extend Pyrameter to support additional shapes (e.g., "Inverted Pyramid" for API-heavy apps):

    // app/Extensions/CustomPyrameter.php
    use Boundwize\Pyrameter\Pyrameter;
    
    class CustomPyrameter extends Pyrameter {
        public function analyze(): Shape {
            $shape = parent::analyze();
            if ($shape->getE2ePercentage() > $shape->getUnitPercentage()) {
                return new InvertedPyramid($shape->getCounts());
            }
            return $shape;
        }
    }
    

    Register in phpunit.xml:

    <extension class="App\Extensions\CustomPyrameter"/>
    
  2. Visualization Integrate with tools like:

    • Graphviz: Generate a visual pyramid from Pyrameter data.
    • Laravel Dashboards: Display pyramid metrics in a dashboard (e.g., using spatie/laravel-dashboard).
  3. Git Hooks Enforce pyramid rules pre-commit:

    composer require --dev phpunit/phpunit
    vendor/bin/phpunit --fail-on-pyrameter-violation
    

    Add to .git/hooks/pre-commit:

    #!/bin/sh
    vendor/bin/phpunit --fail-on-pyrameter-violation || exit 1
    

Configuration Quirks

  1. Case Sensitivity Paths in phpunit.xml are case-sensitive on Linux/macOS but not on Windows. Use absolute paths or normalize:

    <argument name="unitPath" value="./tests/Unit"/>
    
  2. PHPUnit Version

    • Compatibility: Works with PHPUnit 9.x+. For older versions, pin the package:
      composer require boundwize/pyrameter:^1.0 --dev
      
    • Deprecations: Monitor for PHPUnit 10+ changes (e.g., new extension APIs).
  3. Parallel Testing Pyrameter may not work correctly with --parallel due to test classification logic. Use sequential runs for analysis:

    vendor/bin/phpunit --group=unit --group=integration --group=e2e
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata