-
-
Notifications
You must be signed in to change notification settings - Fork 1
Testing
Rumen Damyanov edited this page Oct 28, 2025
·
2 revisions
Comprehensive testing guide for the PHP-SEO package, including unit tests, integration tests, and SEO validation testing.
Testing is crucial for ensuring your SEO implementation works correctly and consistently. This guide covers testing strategies, tools, and best practices for validating SEO functionality with the PHP-SEO package.
Current Test Status:
- ✅ 413 tests passing (100% pass rate)
- 📊 67.5% code coverage (improving towards 80%+ target)
- 🧪 Pest PHP testing framework
- ⚡ ~24s full suite execution time
The php-seo package uses Pest PHP as its testing framework, which provides an elegant, readable syntax for writing tests.
composer require pestphp/pest --dev
composer require pestphp/pest-plugin-laravel --dev # For Laravel projects
# Initialize Pest
./vendor/bin/pest --init- Unit Testing: Test individual components and methods
- Integration Testing: Test component interactions
- Functional Testing: Test complete SEO workflows
- Validation Testing: Verify SEO output correctness
- Performance Testing: Ensure acceptable performance
- Regression Testing: Prevent feature breakage
use Rumenx\PhpSeo\SeoManager;
use Rumenx\PhpSeo\Config\SeoConfig;
test('SeoManager can analyze basic content', function () {
$config = new SeoConfig([
'ai' => ['enabled' => false],
]);
$seoManager = new SeoManager($config);
$html = '<html><head><title>Test Page</title></head><body><h1>Hello World</h1></body></html>';
$analysis = $seoManager->analyze($html);
expect($analysis)->toBeArray()
->and($analysis['title'])->toBe('Test Page')
->and($analysis['headings']['h1'])->toHaveCount(1)
->and($analysis['headings']['h1'][0]['text'])->toBe('Hello World');
});
test('SeoManager generates meta tags', function () {
$config = new SeoConfig();
$seoManager = new SeoManager($config);
$analysis = $seoManager->analyze('<html></html>', [
'title' => 'Custom Title',
'description' => 'Custom description',
]);
$metaTags = $seoManager->renderMetaTags($analysis);
expect($metaTags)->toContain('Custom Title')
->and($metaTags)->toContain('Custom description');
});test('generates title meta tag', function () {
$seo = new SeoManager();
$analysis = $seo->analyze('<html></html>', ['title' => 'Test Title']);
$metaTags = $seo->renderMetaTags($analysis);
expect($metaTags)->toContain('<title>Test Title</title>');
});
test('generates description meta tag', function () {
$seo = new SeoManager();
$analysis = $seo->analyze('<html></html>', [
'description' => 'This is a test description'
]);
$metaTags = $seo->renderMetaTags($analysis);
expect($metaTags)->toContain('<meta name="description" content="This is a test description">');
});
test('generates Open Graph tags', function () {
$seo = new SeoManager();
$analysis = $seo->analyze('<html></html>', [
'title' => 'OG Test',
'description' => 'OG Description',
'image' => 'https://example.com/image.jpg',
'url' => 'https://example.com/page'
]);
$metaTags = $seo->renderMetaTags($analysis);
expect($metaTags)->toContain('<meta property="og:title" content="OG Test">')
->and($metaTags)->toContain('<meta property="og:description" content="OG Description">')
->and($metaTags)->toContain('<meta property="og:image" content="https://example.com/image.jpg">');
});test('generates article schema', function () {
$seo = new SeoManager();
$content = '<article><h1>Article Title</h1><p>Article content</p></article>';
$analysis = $seo->analyze($content, [
'type' => 'article',
'title' => 'Article Title',
'author' => 'John Doe',
'published_at' => '2024-01-01T10:00:00Z'
]);
$structuredData = $seo->generateStructuredData($analysis);
$schema = json_decode($structuredData, true);
expect($schema['@type'])->toBe('Article')
->and($schema['headline'])->toBe('Article Title')
->and($schema['author']['name'])->toBe('John Doe');
});
test('generates product schema', function () {
$seo = new SeoManager();
$analysis = $seo->analyze('<html></html>', [
'type' => 'product',
'name' => 'Test Product',
'price' => 29.99,
'currency' => 'USD'
]);
$structuredData = $seo->generateStructuredData($analysis);
$schema = json_decode($structuredData, true);
expect($schema['@type'])->toBe('Product')
->and($schema['name'])->toBe('Test Product')
->and($schema['offers']['price'])->toBe(29.99);
});test('extracts headings from HTML', function () {
$html = '
<html>
<body>
<h1>Main Title</h1>
<h2>Subtitle 1</h2>
<h2>Subtitle 2</h2>
<h3>Sub-subtitle</h3>
</body>
</html>
';
$seo = new SeoManager();
$analysis = $seo->analyze($html);
expect($analysis['headings']['h1'])->toHaveCount(1)
->and($analysis['headings']['h2'])->toHaveCount(2)
->and($analysis['headings']['h3'])->toHaveCount(1)
->and($analysis['headings']['h1'][0]['text'])->toBe('Main Title');
});
test('analyzes images', function () {
$html = '
<html>
<body>
<img src="image1.jpg" alt="Image 1">
<img src="image2.jpg" alt="">
<img src="image3.jpg">
</body>
</html>
';
$seo = new SeoManager();
$analysis = $seo->analyze($html);
expect($analysis['images'])->toHaveCount(3)
->and($analysis['images'][0]['alt'])->toBe('Image 1')
->and($analysis['images'][1]['alt'])->toBe('');
});# Run all tests
./vendor/bin/pest
# Run with coverage
./vendor/bin/pest --coverage
# Run with minimum coverage threshold
./vendor/bin/pest --coverage --min=70# Run specific test file
./vendor/bin/pest tests/Unit/SeoManagerTest.php
# Run tests matching a pattern
./vendor/bin/pest --filter="SeoManager"
# Run tests in a directory
./vendor/bin/pest tests/Unit/
# Run tests with specific group
./vendor/bin/pest --group=integration// tests/Pest.php
<?php
uses(Tests\TestCase::class)->in('Feature');
/*
|--------------------------------------------------------------------------
| Expectations
|--------------------------------------------------------------------------
*/
expect()->extend('toBeOne', function () {
return $this->toBe(1);
});
/*
|--------------------------------------------------------------------------
| Functions
|--------------------------------------------------------------------------
*/
function something()
{
// ..
}# .github/workflows/tests.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: ['8.2', '8.3']
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: dom, curl, libxml, mbstring, zip
coverage: xdebug
- name: Install dependencies
run: composer install --prefer-dist --no-progress
- name: Run tests
run: vendor/bin/pest --coverage --min=70
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage.xmlThe package currently achieves 67.5% code coverage with ongoing improvements. Coverage gaps are primarily in:
- AI Provider HTTP methods (require extensive mocking)
- Error handling edge cases
- Framework-specific integrations
High Coverage Areas:
- ✅ ContentAnalyzer: 100%
- ✅ SeoConfig: 100%
- ✅ MetaTagGenerator: 100%
- ✅ PromptBuilder: 98.3%
- ✅ ResponseValidator: 92%
- ✅ ProviderFactory: 92%
Testing ensures your SEO implementation is reliable, maintainable, and performs well across different scenarios and environments.