Pokrytí kódu

Školení, která pořádám

Při testování kódu je dobré vědět, kolik jsme ho vlastně otestovali. Slouží k tomu tzv. coverage report a v PHP je možné ho získat pomocí extenze XDebug:

<?php
xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);

// spuštění kódu, který chceme analyzovat

$coverage = xdebug_get_code_coverage();
$coverage = $coverage[realpath($filename)];
foreach (file($filename) as $l => $line) {
    $color = "Green"; // tested
    switch ($coverage[$l+1]) {
        case -1: $color = "Red"; break; // untested
        case -2: $color = "Gray"; break; // dead code
        case null: $color = ""; break; // not executable
    }
    echo "<pre" . ($color ? " style='background-color: $color;'" : "") . ">" . htmlspecialchars($line) . "</pre>\n";
}
?>

Na co si u zdrojového kódu potrpím, je barevné zvýraznění syntaxe. K tomu se v PHP dá použít funkce highlight_file. Pokud do takto zvýrazněného kódu chceme doplnit pozadí jednotlivých řádek, musíme kód rozebrat a zpátky složit podle obarvených řádek. Vzhledem k tomu, že HTML neumožňuje křížení značek, tak to je poměrně pracné. Pro jednotlivé bloky musíme nalézt neuzavřené značky, uzavřít je a po nastavení barvy zase otevřít:

<?php
/** Nalezení neuzavřených značek v XHTML kódu
* @param string fragment XHTML kódu
* @return array seznam neuzavřených značek ve tvaru array("značka atributy", ...)
* @copyright Jakub Vrána, https://php.vrana.cz/
*/
function xhtml_open_tags($s) {
    $return = array();
    preg_match_all('~<([^>]+)~', $s, $matches);
    foreach ($matches[1] as $val) {
        if ($val[0] == "/") {
            array_pop($return);
        } elseif (substr($val, -1) != "/") {
            $return[] = $val;
        }
    }
    return $return;
}

$file = explode("<br />", highlight_file($filename, true));
unset($prev_color);
$s = "";
for ($l=0; $l <= count($file); $l++) {
    $line = $file[$l];
    $color = "#C0FFC0"; // tested
    switch ($coverage[$l+1]) {
        case -1: $color = "#FFC0C0"; break; // untested
        case -2: $color = "Silver"; break; // dead code
        case null: $color = ""; break; // not executable
    }
    if (!isset($prev_color)) {
        $prev_color = $color;
    }
    if ($prev_color != $color || !isset($line)) {
        echo "<div" . ($prev_color ? " style='background-color: $prev_color;'" : "") . ">" . $s;
        $open_tags = xhtml_open_tags($s);
        foreach (array_reverse($open_tags) as $tag) {
            echo "</" . preg_replace('~ .*~', '', $tag) . ">";
        }
        echo "</div>\n";
        $s = ($open_tags ? "<" . implode("><", $open_tags) . ">" : "");
        $prev_color = $color;
    }
    $s .= "$line<br />\n";
}
?>

Závěr

Samotné 100% pokrytí kódu testy nám ještě nedává jistotu, že je kód v pořádku, protože např. nemusí být správně ošetřeny všechny vstupy.

Jakub Vrána, Seznámení s oblastí, 20.8.2008, diskuse: 1 (nové: 0)

Diskuse

ikona Jakub Vrána OpenID:

Ukázka výstupu: http://php.vrana.cz/data/php-initialized-coverage.html

Diskuse je zrušena z důvodu spamu.

avatar © 2005-2024 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.