php-webdriver测试报告自动化:从生成到分享的完整流程

php-webdriver测试报告自动化:从生成到分享的完整流程

【免费下载链接】php-webdriver PHP client for Selenium/WebDriver protocol. Previously facebook/php-webdriver 【免费下载链接】php-webdriver 项目地址: https://gitcode.com/gh_mirrors/ph/php-webdriver

引言:测试报告自动化的痛点与解决方案

在Web应用开发中,测试报告是质量保障的关键环节。传统手动生成报告的方式存在效率低下、易出错、难以追溯等问题。本文将详细介绍如何使用php-webdriver(PHP client for Selenium/WebDriver protocol)构建一套完整的测试报告自动化流程,从测试执行、结果收集、报告生成到最终分享,全方位提升测试效率和报告质量。

读完本文,你将能够:

  • 使用php-webdriver编写自动化测试用例
  • 实现测试结果的自动收集和整理
  • 生成美观、详细的HTML测试报告
  • 通过邮件和Web界面分享测试报告
  • 构建可持续集成的测试报告自动化流程

1. 环境准备与基础配置

1.1 系统环境要求

软件/工具版本要求作用
PHP7.4+运行测试脚本和处理报告
Composer2.0+PHP依赖管理
Selenium Server3.141.59+WebDriver协议服务端
Chrome/Firefox最新稳定版浏览器自动化
ChromeDriver/GeckoDriver匹配浏览器版本浏览器驱动

1.2 安装php-webdriver

通过Composer安装php-webdriver:

composer require php-webdriver/webdriver

1.3 基础配置

创建config.php文件,配置测试环境:

<?php
return [
    'selenium_server_url' => 'http://localhost:4444/wd/hub',
    'browser' => 'chrome', // 或 'firefox'
    'base_url' => 'http://your-web-app-url',
    'test_report_dir' => __DIR__ . '/reports',
    'screenshot_dir' => __DIR__ . '/reports/screenshots',
    'mail_config' => [
        'smtp_server' => 'smtp.example.com',
        'smtp_port' => 587,
        'smtp_username' => 'your-email@example.com',
        'smtp_password' => 'your-password',
        'from_email' => 'test-report@example.com',
        'to_email' => 'stakeholders@example.com',
    ],
];

2. 使用php-webdriver编写自动化测试用例

2.1 测试用例基础结构

创建tests/ExampleTest.php,定义基本测试类:

<?php
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\WebDriverExpectedCondition;
use Facebook\WebDriver\WebDriverWait;
use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    protected $driver;
    protected $config;
    protected $testResults = [];
    protected $testName;

    protected function setUp(): void
    {
        $this->config = require __DIR__ . '/../config.php';
        
        // 初始化WebDriver
        $capabilities = match ($this->config['browser']) {
            'firefox' => DesiredCapabilities::firefox(),
            default => DesiredCapabilities::chrome()
        };
        $this->driver = RemoteWebDriver::create(
            $this->config['selenium_server_url'],
            $capabilities
        );
        
        // 设置隐式等待时间
        $this->driver->manage()->timeouts()->implicitlyWait(10);
        
        // 记录测试名称
        $this->testName = $this->getName();
        $this->testResults[$this->testName] = [
            'status' => 'running',
            'start_time' => date('Y-m-d H:i:s'),
            'steps' => [],
            'screenshots' => [],
            'error' => null
        ];
    }

    protected function tearDown(): void
    {
        // 记录测试结束时间和状态
        $this->testResults[$this->testName]['end_time'] = date('Y-m-d H:i:s');
        $this->testResults[$this->testName]['status'] = $this->getStatus();
        
        // 保存测试结果
        $this->saveTestResults();
        
        // 关闭浏览器
        if ($this->driver) {
            $this->driver->quit();
        }
    }
    
    // 测试结果保存逻辑
    private function saveTestResults()
    {
        $resultsFile = $this->config['test_report_dir'] . '/test_results.json';
        $allResults = file_exists($resultsFile) ? json_decode(file_get_contents($resultsFile), true) : [];
        $allResults[$this->testName] = $this->testResults[$this->testName];
        file_put_contents($resultsFile, json_encode($allResults, JSON_PRETTY_PRINT));
    }
    
    // 获取测试状态
    private function getStatus()
    {
        if ($this->hasFailed()) {
            return 'failed';
        }
        if ($this->wasSkipped()) {
            return 'skipped';
        }
        return 'passed';
    }
}

2.2 添加测试步骤和结果记录

扩展上述测试类,添加具体测试步骤和结果记录功能:

// 在ExampleTest类中添加以下方法

/**
 * 记录测试步骤
 */
protected function logStep($description, $status = 'info')
{
    $this->testResults[$this->testName]['steps'][] = [
        'description' => $description,
        'status' => $status,
        'timestamp' => date('Y-m-d H:i:s')
    ];
}

/**
 * 捕获屏幕截图
 */
protected function takeScreenshot($stepName)
{
    $screenshotDir = $this->config['screenshot_dir'] . '/' . $this->testName;
    if (!file_exists($screenshotDir)) {
        mkdir($screenshotDir, 0777, true);
    }
    
    $screenshotPath = $screenshotDir . '/' . $stepName . '_' . date('YmdHis') . '.png';
    
    // 使用ScreenshotHelper捕获页面截图
    $screenshotHelper = new \Facebook\WebDriver\Support\ScreenshotHelper(
        new \Facebook\WebDriver\Remote\RemoteExecuteMethod($this->driver)
    );
    $screenshotHelper->takePageScreenshot($screenshotPath);
    
    $this->testResults[$this->testName]['screenshots'][] = [
        'step' => $stepName,
        'path' => $screenshotPath,
        'timestamp' => date('Y-m-d H:i:s')
    ];
    
    return $screenshotPath;
}

/**
 * 示例测试用例
 */
public function testLoginFunctionality()
{
    try {
        $this->logStep('打开登录页面');
        $this->driver->get($this->config['base_url'] . '/login');
        $this->takeScreenshot('open_login_page');
        
        $this->logStep('输入用户名');
        $usernameField = $this->driver->findElement(WebDriverBy::id('username'));
        $usernameField->sendKeys('testuser');
        $this->takeScreenshot('enter_username');
        
        $this->logStep('输入密码');
        $passwordField = $this->driver->findElement(WebDriverBy::id('password'));
        $passwordField->sendKeys('testpassword');
        $this->takeScreenshot('enter_password');
        
        $this->logStep('点击登录按钮');
        $loginButton = $this->driver->findElement(WebDriverBy::id('login-btn'));
        $loginButton->click();
        $this->takeScreenshot('click_login');
        
        $this->logStep('验证登录成功');
        $wait = new WebDriverWait($this->driver, 10);
        $dashboardElement = $wait->until(
            WebDriverExpectedCondition::presenceOfElementLocated(WebDriverBy::id('dashboard'))
        );
        $this->assertTrue($dashboardElement->isDisplayed());
        $this->takeScreenshot('login_success');
        
        $this->logStep('测试完成', 'success');
    } catch (\Exception $e) {
        $this->logStep('测试失败: ' . $e->getMessage(), 'error');
        $this->takeScreenshot('test_failed');
        $this->testResults[$this->testName]['error'] = $e->getMessage() . "\n" . $e->getTraceAsString();
        throw $e;
    }
}

3. 测试结果收集与处理

3.1 测试结果数据结构

测试结果JSON文件结构示例:

{
  "testLoginFunctionality": {
    "status": "passed",
    "start_time": "2025-09-23 10:00:00",
    "end_time": "2025-09-23 10:00:30",
    "steps": [
      {
        "description": "打开登录页面",
        "status": "info",
        "timestamp": "2025-09-23 10:00:02"
      },
      // ...其他步骤
    ],
    "screenshots": [
      {
        "step": "open_login_page",
        "path": "/path/to/screenshots/testLoginFunctionality/open_login_page_20250923100002.png",
        "timestamp": "2025-09-23 10:00:02"
      },
      // ...其他截图
    ],
    "error": null
  }
}

3.2 测试结果合并工具

创建scripts/merge-test-results.php,合并多个测试文件的结果:

<?php
$config = require __DIR__ . '/../config.php';
$reportsDir = $config['test_report_dir'];

$allResults = [];
$resultsFiles = glob($reportsDir . '/test_results_*.json');

foreach ($resultsFiles as $file) {
    $content = file_get_contents($file);
    $results = json_decode($content, true);
    if ($results) {
        $allResults = array_merge($allResults, $results);
    }
}

// 按测试执行时间排序
usort($allResults, function($a, $b) {
    return strtotime($a['start_time']) - strtotime($b['start_time']);
});

// 保存合并后的结果
$mergedFile = $reportsDir . '/merged_test_results.json';
file_put_contents($mergedFile, json_encode($allResults, JSON_PRETTY_PRINT));

echo "合并完成,共处理 " . count($allResults) . " 个测试用例\n";
echo "结果保存至: " . $mergedFile . "\n";

4. 测试报告生成

4.1 报告模板设计

创建templates/report-template.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自动化测试报告 - {{DATE}}</title>
    <style>
        /* 报告样式 */
        body { font-family: Arial, sans-serif; line-height: 1.6; margin: 0; padding: 20px; color: #333; }
        .header { background-color: #f5f5f5; padding: 20px; border-radius: 5px; margin-bottom: 20px; }
        .summary { display: flex; gap: 20px; margin-bottom: 30px; }
        .summary-item { flex: 1; background-color: #e9f5ff; padding: 15px; border-radius: 5px; text-align: center; }
        .summary-item h3 { margin-top: 0; color: #333; }
        .summary-item .count { font-size: 2em; font-weight: bold; margin: 10px 0; }
        .passed { color: #4CAF50; }
        .failed { color: #F44336; }
        .skipped { color: #FFC107; }
        .test-case { border: 1px solid #ddd; border-radius: 5px; margin-bottom: 20px; overflow: hidden; }
        .test-case-header { background-color: #f9f9f9; padding: 15px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; }
        .test-case-header h3 { margin: 0; }
        .test-case-body { padding: 0 15px; max-height: 0; overflow: hidden; transition: max-height 0.3s ease; }
        .test-case.expanded .test-case-body { padding: 15px; max-height: 5000px; }
        .steps { list-style-type: none; padding: 0; }
        .step { margin-bottom: 15px; padding: 10px; border-left: 3px solid #ddd; }
        .step.info { border-left-color: #2196F3; }
        .step.success { border-left-color: #4CAF50; }
        .step.error { border-left-color: #F44336; background-color: #fff5f5; }
        .screenshots { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 15px; }
        .screenshot-item { flex: 1; min-width: 200px; max-width: 300px; }
        .screenshot-item img { width: 100%; border-radius: 5px; border: 1px solid #ddd; }
        .timestamp { color: #777; font-size: 0.8em; margin-top: 5px; }
        .error-details { background-color: #ffebee; padding: 15px; border-radius: 5px; margin-top: 10px; }
    </style>
</head>
<body>
    <div class="header">
        <h1>自动化测试报告</h1>
        <p>项目: {{PROJECT_NAME}}</p>
        <p>生成时间: {{DATE}}</p>
        <p>测试环境: {{ENVIRONMENT}}</p>
    </div>

    <div class="summary">
        <div class="summary-item">
            <h3>总测试用例</h3>
            <div class="count">{{TOTAL}}</div>
        </div>
        <div class="summary-item">
            <h3>通过</h3>
            <div class="count passed">{{PASSED}}</div>
        </div>
        <div class="summary-item">
            <h3>失败</h3>
            <div class="count failed">{{FAILED}}</div>
        </div>
        <div class="summary-item">
            <h3>跳过</h3>
            <div class="count skipped">{{SKIPPED}}</div>
        </div>
        <div class="summary-item">
            <h3>通过率</h3>
            <div class="count">{{PASS_RATE}}%</div>
        </div>
    </div>

    <div class="test-cases">
        <h2>测试用例详情</h2>
        {{TEST_CASES}}
    </div>

    <script>
        // 点击测试用例标题展开/折叠详情
        document.querySelectorAll('.test-case-header').forEach(header => {
            header.addEventListener('click', () => {
                header.parentElement.classList.toggle('expanded');
            });
        });
    </script>
</body>
</html>

4.2 报告生成脚本

创建scripts/generate-report.php

<?php
$config = require __DIR__ . '/../config.php';
$reportsDir = $config['test_report_dir'];
$mergedResultsFile = $reportsDir . '/merged_test_results.json';
$templateFile = __DIR__ . '/../templates/report-template.html';
$outputFile = $reportsDir . '/test_report_' . date('YmdHis') . '.html';

// 读取合并后的测试结果
if (!file_exists($mergedResultsFile)) {
    die("错误: 未找到测试结果文件 " . $mergedResultsFile);
}

$results = json_decode(file_get_contents($mergedResultsFile), true);
if (!$results) {
    die("错误: 无法解析测试结果文件");
}

// 读取模板文件
if (!file_exists($templateFile)) {
    die("错误: 未找到模板文件 " . $templateFile);
}

$template = file_get_contents($templateFile);

// 统计测试结果
$total = count($results);
$passed = 0;
$failed = 0;
$skipped = 0;

foreach ($results as $test) {
    switch ($test['status']) {
        case 'passed':
            $passed++;
            break;
        case 'failed':
            $failed++;
            break;
        case 'skipped':
            $skipped++;
            break;
    }
}

$passRate = $total > 0 ? round(($passed / $total) * 100, 2) : 0;

// 生成测试用例详情HTML
$testCasesHtml = '';
foreach ($results as $testName => $testData) {
    $statusClass = match ($testData['status']) {
        'passed' => 'passed',
        'failed' => 'failed',
        'skipped' => 'skipped',
        default => ''
    };
    
    // 步骤HTML
    $stepsHtml = '<ul class="steps">';
    foreach ($testData['steps'] as $step) {
        $stepsHtml .= '<li class="step ' . $step['status'] . '">';
        $stepsHtml .= '<strong>' . htmlspecialchars($step['timestamp']) . '</strong>: ';
        $stepsHtml .= htmlspecialchars($step['description']);
        $stepsHtml .= '</li>';
    }
    $stepsHtml .= '</ul>';
    
    // 截图HTML
    $screenshotsHtml = '';
    if (!empty($testData['screenshots'])) {
        $screenshotsHtml .= '<div class="screenshots">';
        foreach ($testData['screenshots'] as $screenshot) {
            $screenshotRelativePath = str_replace($reportsDir . '/', '', $screenshot['path']);
            $screenshotsHtml .= '<div class="screenshot-item">';
            $screenshotsHtml .= '<h4>' . htmlspecialchars($screenshot['step']) . '</h4>';
            $screenshotsHtml .= '<img src="' . $screenshotRelativePath . '" alt="Screenshot for ' . htmlspecialchars($screenshot['step']) . '">';
            $screenshotsHtml .= '<div class="timestamp">' . htmlspecialchars($screenshot['timestamp']) . '</div>';
            $screenshotsHtml .= '</div>';
        }
        $screenshotsHtml .= '</div>';
    }
    
    // 错误信息HTML
    $errorHtml = '';
    if (!empty($testData['error'])) {
        $errorHtml .= '<div class="error-details">';
        $errorHtml .= '<h4>错误详情:</h4>';
        $errorHtml .= '<pre>' . htmlspecialchars($testData['error']) . '</pre>';
        $errorHtml .= '</div>';
    }
    
    // 测试用例HTML
    $testCasesHtml .= '<div class="test-case">';
    $testCasesHtml .= '<div class="test-case-header">';
    $testCasesHtml .= '<h3>' . htmlspecialchars($testName) . '</h3>';
    $testCasesHtml .= '<span class="status ' . $statusClass . '">' . strtoupper($testData['status']) . '</span>';
    $testCasesHtml .= '</div>';
    $testCasesHtml .= '<div class="test-case-body">';
    $testCasesHtml .= '<p><strong>开始时间:</strong> ' . htmlspecialchars($testData['start_time']) . '</p>';
    $testCasesHtml .= '<p><strong>结束时间:</strong> ' . htmlspecialchars($testData['end_time']) . '</p>';
    $testCasesHtml .= '<h4>测试步骤:</h4>';
    $testCasesHtml .= $stepsHtml;
    if ($screenshotsHtml) {
        $testCasesHtml .= '<h4>截图:</h4>';
        $testCasesHtml .= $screenshotsHtml;
    }
    $testCasesHtml .= $errorHtml;
    $testCasesHtml .= '</div>';
    $testCasesHtml .= '</div>';
}

// 替换模板变量
$template = str_replace('{{DATE}}', date('Y-m-d H:i:s'), $template);
$template = str_replace('{{PROJECT_NAME}}', 'php-webdriver测试项目', $template);
$template = str_replace('{{ENVIRONMENT}}', $config['browser'] . ' / ' . $config['base_url'], $template);
$template = str_replace('{{TOTAL}}', $total, $template);
$template = str_replace('{{PASSED}}', $passed, $template);
$template = str_replace('{{FAILED}}', $failed, $template);
$template = str_replace('{{SKIPPED}}', $skipped, $template);
$template = str_replace('{{PASS_RATE}}', $passRate, $template);
$template = str_replace('{{TEST_CASES}}', $testCasesHtml, $template);

// 保存生成的报告
file_put_contents($outputFile, $template);

echo "报告生成成功: " . $outputFile . "\n";

5. 测试报告分享机制

5.1 邮件发送功能

创建scripts/send-report-email.php

<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require __DIR__ . '/../vendor/autoload.php';

$config = require __DIR__ . '/../config.php';
$reportsDir = $config['test_report_dir'];

// 获取最新的测试报告
$reportFiles = glob($reportsDir . '/test_report_*.html');
if (empty($reportFiles)) {
    die("错误: 未找到测试报告文件");
}

// 按修改时间排序,获取最新的报告
usort($reportFiles, function($a, $b) {
    return filemtime($b) - filemtime($a);
});
$latestReportFile = $reportFiles[0];

// 创建邮件
$mail = new PHPMailer(true);

try {
    // 服务器配置
    $mail->isSMTP();
    $mail->Host = $config['mail_config']['smtp_server'];
    $mail->SMTPAuth = true;
    $mail->Username = $config['mail_config']['smtp_username'];
    $mail->Password = $config['mail_config']['smtp_password'];
    $mail->SMTPSecure = 'tls';
    $mail->Port = $config['mail_config']['smtp_port'];

    // 收件人
    $mail->setFrom($config['mail_config']['from_email'], '自动化测试报告');
    $mail->addAddress($config['mail_config']['to_email']);
    
    // 邮件内容
    $mail->isHTML(true);
    $mail->Subject = '[' . date('Y-m-d') . '] 自动化测试报告';
    $mail->Body = '
        <h2>自动化测试报告</h2>
        <p>测试报告已生成,详情请查看附件。</p>
        <p>生成时间: ' . date('Y-m-d H:i:s') . '</p>
        <p>报告文件: ' . basename($latestReportFile) . '</p>
    ';
    $mail->AltBody = '自动化测试报告已生成,请查看附件。';
    
    // 添加报告附件
    $mail->addAttachment($latestReportFile);
    
    // 发送邮件
    $mail->send();
    echo "邮件发送成功!\n";
} catch (Exception $e) {
    echo "邮件发送失败: {$mail->ErrorInfo}\n";
}

5.2 Web界面展示

创建web/index.php,实现报告的Web访问:

<?php
$config = require __DIR__ . '/../config.php';
$reportsDir = $config['test_report_dir'];

// 获取所有测试报告
$reportFiles = glob($reportsDir . '/test_report_*.html');
usort($reportFiles, function($a, $b) {
    return filemtime($b) - filemtime($a);
});

// 获取所有截图目录
$screenshotDirs = glob($reportsDir . '/screenshots/*', GLOB_ONLYDIR);
usort($screenshotDirs, function($a, $b) {
    return filemtime($b) - filemtime($a);
});
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>测试报告列表</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto; padding: 20px; }
        .header { text-align: center; margin-bottom: 30px; }
        .report-list, .screenshot-list { margin-bottom: 40px; }
        .list-item { border: 1px solid #ddd; padding: 15px; margin-bottom: 10px; border-radius: 5px; }
        .list-item h3 { margin-top: 0; }
        .timestamp { color: #666; font-size: 0.9em; }
        a { color: #2196F3; text-decoration: none; }
        a:hover { text-decoration: underline; }
    </style>
</head>
<body>
    <div class="header">
        <h1>自动化测试报告</h1>
        <p>项目: php-webdriver测试项目</p>
    </div>

    <div class="report-list">
        <h2>测试报告列表</h2>
        <?php if (empty($reportFiles)): ?>
            <p>暂无测试报告</p>
        <?php else: ?>
            <?php foreach ($reportFiles as $file): ?>
                <div class="list-item">
                    <h3><a href="../<?= str_replace($_SERVER['DOCUMENT_ROOT'], '', $file) ?>" target="_blank"><?= basename($file) ?></a></h3>
                    <div class="timestamp">生成时间: <?= date('Y-m-d H:i:s', filemtime($file)) ?></div>
                    <div>大小: <?= round(filesize($file) / 1024, 2) ?> KB</div>
                </div>
            <?php endforeach; ?>
        <?php endif; ?>
    </div>

    <div class="screenshot-list">
        <h2>截图目录</h2>
        <?php if (empty($screenshotDirs)): ?>
            <p>暂无截图</p>
        <?php else: ?>
            <?php foreach ($screenshotDirs as $dir): ?>
                <div class="list-item">
                    <h3><a href="screenshots.php?dir=<?= urlencode(basename($dir)) ?>"><?= basename($dir) ?></a></h3>
                    <div class="timestamp">修改时间: <?= date('Y-m-d H:i:s', filemtime($dir)) ?></div>
                </div>
            <?php endforeach; ?>
        <?php endif; ?>
    </div>
</body>
</html>

创建web/screenshots.php,实现截图查看功能:

<?php
$config = require __DIR__ . '/../config.php';
$reportsDir = $config['test_report_dir'];
$screenshotBaseDir = $reportsDir . '/screenshots';

if (!isset($_GET['dir']) || empty($_GET['dir'])) {
    die("错误: 未指定截图目录");
}

$dirName = basename($_GET['dir']); // 防止路径遍历攻击
$targetDir = $screenshotBaseDir . '/' . $dirName;

if (!is_dir($targetDir)) {
    die("错误: 截图目录不存在");
}

// 获取目录中的所有图片
$imageFiles = glob($targetDir . '/*.{png,jpg,jpeg,gif}', GLOB_BRACE);
usort($imageFiles, function($a, $b) {
    return filemtime($a) - filemtime($b);
});
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>截图查看 - <?= htmlspecialchars($dirName) ?></title>
    <style>
        body { font-family: Arial, sans-serif; padding: 20px; }
        .back-link { margin-bottom: 20px; }
        .screenshots { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
        .screenshot-item { border: 1px solid #ddd; padding: 10px; border-radius: 5px; }
        .screenshot-item img { width: 100%; height: auto; border-radius: 5px; }
        .screenshot-info { margin-top: 10px; }
    </style>
</head>
<body>
    <div class="back-link">
        <a href="index.php">&laquo; 返回报告列表</a>
    </div>
    
    <h1>截图目录: <?= htmlspecialchars($dirName) ?></h1>
    
    <div class="screenshots">
        <?php if (empty($imageFiles)): ?>
            <p>此目录中没有图片</p>
        <?php else: ?>
            <?php foreach ($imageFiles as $file): ?>
                <div class="screenshot-item">
                    <h3><?= htmlspecialchars(basename($file)) ?></h3>
                    <img src="<?= str_replace($_SERVER['DOCUMENT_ROOT'], '', $file) ?>" alt="Screenshot">
                    <div class="screenshot-info">
                        <div>修改时间: <?= date('Y-m-d H:i:s', filemtime($file)) ?></div>
                        <div>大小: <?= round(filesize($file) / 1024, 2) ?> KB</div>
                    </div>
                </div>
            <?php endforeach; ?>
        <?php endif; ?>
    </div>
</body>
</html>

6. 自动化流程整合与CI/CD集成

6.1 一键执行脚本

创建run-all.sh

#!/bin/bash

# 确保报告目录存在
mkdir -p reports/screenshots

# 运行测试
vendor/bin/phpunit tests/

# 合并测试结果
php scripts/merge-test-results.php

# 生成测试报告
php scripts/generate-report.php

# 发送报告邮件
php scripts/send-report-email.php

echo "自动化测试报告流程完成!"

6.2 GitLab CI/CD配置

创建.gitlab-ci.yml

stages:
  - test
  - report

variables:
  PHPUNIT_FLAGS: "--configuration phpunit.xml.dist"

test:
  stage: test
  image: php:7.4-cli
  services:
    - selenium/standalone-chrome:latest
  before_script:
    - apt-get update && apt-get install -y unzip libzip-dev libcurl4-openssl-dev
    - docker-php-ext-install zip curl
    - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
    - composer install --no-interaction
  script:
    - vendor/bin/phpunit $PHPUNIT_FLAGS
  artifacts:
    paths:
      - reports/
    expire_in: 1 week

generate_and_share_report:
  stage: report
  image: php:7.4-cli
  before_script:
    - apt-get update && apt-get install -y libcurl4-openssl-dev
    - docker-php-ext-install curl
    - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
    - composer install --no-interaction
  script:
    - php scripts/merge-test-results.php
    - php scripts/generate-report.php
    - php scripts/send-report-email.php
  dependencies:
    - test
  only:
    - master
    - develop

7. 总结与最佳实践

7.1 完整流程图

mermaid

7.2 最佳实践总结

  1. 测试用例设计

    • 每个测试用例应专注于单一功能点
    • 关键步骤必须添加截图,便于问题定位
    • 使用显式等待而非固定延迟,提高测试稳定性
  2. 报告内容优化

    • 包含关键指标:测试总数、通过数、失败数、通过率
    • 错误信息需包含完整堆栈跟踪,便于调试
    • 截图需关联具体测试步骤,添加时间戳
  3. 性能与可维护性

    • 测试报告和截图定期清理,避免磁盘空间耗尽
    • 使用模板引擎分离报告结构和样式
    • 关键配置参数化,便于环境切换
  4. 集成与自动化

    • 与CI/CD流程深度集成,实现每次提交自动测试
    • 报告生成和分享完全自动化,减少人工干预
    • 建立报告版本管理,便于历史对比分析

通过本文介绍的方法,你可以构建一套完整的php-webdriver测试报告自动化流程,从测试执行到报告分享全链路自动化,显著提升测试效率和报告质量,为Web应用质量保障提供有力支持。

【免费下载链接】php-webdriver PHP client for Selenium/WebDriver protocol. Previously facebook/php-webdriver 【免费下载链接】php-webdriver 项目地址: https://gitcode.com/gh_mirrors/ph/php-webdriver

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值