Skip to content

Commit

Permalink
Beholder: Refactored output for more variability
Browse files Browse the repository at this point in the history
  • Loading branch information
finwe authored and kukulich committed Jul 14, 2017
1 parent e1ea98f commit b08b902
Show file tree
Hide file tree
Showing 7 changed files with 452 additions and 173 deletions.
199 changes: 26 additions & 173 deletions Jyxo/Beholder/Executor.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@

namespace Jyxo\Beholder;

use Jyxo\Beholder\Output\HtmlOutput;
use Jyxo\Beholder\Output\JsonOutput;
use Jyxo\Beholder\Output\NoOutput;
use Jyxo\Beholder\Output\Output;
use Jyxo\Beholder\Output\TextOutput;
use Jyxo\Beholder\Result\TestSuiteResult;

/**
* Beholder test executor.
*
Expand Down Expand Up @@ -179,9 +186,11 @@ public function setParams(array $params)
/**
* Performs chosen tests and outputs results according to the selected output type.
*
* @return boolean Returns if all tests were successful
* @param bool $print
*
* @return \Jyxo\Beholder\Output\Output
*/
public function run(): bool
public function run($print = true): Output
{
// Filters tests
foreach (array_keys($this->tests) as $ident) {
Expand Down Expand Up @@ -216,35 +225,42 @@ public function run(): bool
}
array_multisort($idents, SORT_ASC, $this->testsData);

if ($this->output === self::OUTPUT_NOTHING) {
return $allSucceeded;
}

// Outputs the header
if ($allSucceeded) {
header('HTTP/1.1 200 OK');
} else {
header('HTTP/1.1 500 Internal Server Error');
}

$result = new TestSuiteResult($this->project, $allSucceeded, $this->testsData, $this->includeFilter, $this->excludeFilter);

// Outputs the output :)
switch ($this->output) {
// No output
case self::OUTPUT_NOTHING:
$output = new NoOutput($result);
break;
// Plaintext
case self::OUTPUT_TEXT:
$this->writeText($allSucceeded);
$output = new TextOutput($result);
break;
// JSON
case self::OUTPUT_JSON:
$this->writeJson($allSucceeded);
$output = new JsonOutput($result);
break;
// HTML
case self::OUTPUT_HTML:
default:
$this->writeHtml($allSucceeded);
$output = new HtmlOutput($result);
break;
}

return $allSucceeded;
if ($print) {
header(sprintf('Content-type: %s', $output->getContentType()));
echo (string) $output;
}

return $output;
}

/**
Expand Down Expand Up @@ -339,167 +355,4 @@ private function patternMatch(string $pattern, string $string): bool
return fnmatch($pattern, $string);
}

/**
* Outputs results in HTML form.
*
* @param boolean $allSucceeded Have all tests been successful
*/
private function writeHtml(bool $allSucceeded)
{
header('Content-Type: text/html; charset=utf-8');
echo '<head>' . "\n";
echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />' . "\n";
echo '<title>Beholder for project ' . $this->project . '</title>' . "\n";
echo '<style>' . "\n";
echo ' body {font: 12px Verdana, Geneva, Arial, Helvetica, sans-serif;}' . "\n";
echo ' table {font-size: small; border-collapse: collapse;}' . "\n";
echo ' table th {border: 1px solid #000; background: #000; color: #fff;}' . "\n";
echo ' table td {border: 1px solid #000; padding: .25em .5em;}' . "\n";
echo '</style>' . "\n";
echo '</head>' . "\n";
echo '<body style="background-color: ' . ($allSucceeded ? '#ccffcc' : '#ffcccc') . '; width: 90%; height: 100%; padding: 1em; margin: 0;">' . "\n";
echo '<h1>Beholder for project ' . $this->project . "</h1>\n";
echo '<p>Tests included: ' . $this->includeFilter . "\n";
echo '<br>Tests excluded: ' . $this->excludeFilter . "\n";
echo '</p>' . "\n";
echo '<table><tr><th>Run order</th><th>Duration</th><th>Ident</th><th>Status</th><th>Test name</th><th>Comment</th></tr>' . "\n";
foreach ($this->testsData as $data) {
echo sprintf('
<tr>
<td>%d</td>
<td>%.2fs</td>
<td>%s</td>
<td style="color: %s;">%s</td>
<td><b>%s</b></td>
<td><i>%s</i></td>
</tr>' . "\n",
$data['order'],
$data['duration'],
$data['ident'],
$data['result']->isSuccess() ? 'green' : 'red; font-weight: bold;', $data['result']->getStatusMessage(),
$data['test']->getDescription(),
$data['result']->getDescription()
);
}
echo '</table>
<h2>Parameters</h2>
<dl>
<dt>' . self::PARAM_INCLUDE . '</dt>
<dd>Tests to include, list of shell patterns separated by comma, default *</dd>
<dt>' . self::PARAM_EXCLUDE . '</dt>
<dd>Tests to exclude, empty by default</dd>
<dt>' . self::PARAM_OUTPUT . '</dt>
<dd>' . self::OUTPUT_HTML . ' = HTML output, ' . self::OUTPUT_TEXT . ' = text output, ' . self::OUTPUT_JSON . ' = JSON output</dd>
</dl>
<p>Tests are included, then excluded.</p>
<p><a href="?' . self::PARAM_INCLUDE . '=' . $this->includeFilter
. '&amp;' . self::PARAM_EXCLUDE . '=' . $this->excludeFilter
. '&amp;' . self::PARAM_OUTPUT . '=' . self::OUTPUT_TEXT . '">Text version</a></p>
<p><a href="?' . self::PARAM_INCLUDE . '=' . $this->includeFilter
. '&amp;' . self::PARAM_EXCLUDE . '=' . $this->excludeFilter
. '&amp;' . self::PARAM_OUTPUT . '=' . self::OUTPUT_JSON . '">JSON version</a></p>
</body>' . "\n";
}

/**
* Outputs results in plaintext.
*
* @param boolean $allSucceeded Have all tests been successful
*/
private function writeText(bool $allSucceeded)
{
// HTML is sent on purpose
header('Content-Type: text/html; charset=utf-8');
echo '<pre>This is Beholder for project ' . $this->project . "\n";
echo 'Tests included: ' . $this->includeFilter . "\n";
echo 'Tests excluded: ' . $this->excludeFilter . "\n\n";
echo '<a href="?' . self::PARAM_INCLUDE . '=' . $this->includeFilter
. '&amp;' . self::PARAM_EXCLUDE . '=' . $this->excludeFilter
. '&amp;' . self::PARAM_OUTPUT . '=' . self::OUTPUT_HTML . "\">Html version</a>\n\n";
echo '<a href="?' . self::PARAM_INCLUDE . '=' . $this->includeFilter
. '&amp;' . self::PARAM_EXCLUDE . '=' . $this->excludeFilter
. '&amp;' . self::PARAM_OUTPUT . '=' . self::OUTPUT_JSON . "\">JSON version</a>\n\n";

echo sprintf("%-9s %10s %-10s %-7s %-35s %s\n",
'Run Order', 'Duration', 'Ident', 'Status', 'Test Name', 'Description');
foreach ($this->testsData as $data) {
echo sprintf("%9d %9.2fs %-10s %-7s %-35s %s\n",
$data['order'],
$data['duration'],
$data['ident'],
$data['result']->getStatusMessage(),
$data['test']->getDescription(),
$data['result']->getDescription());
}

if ($allSucceeded) {
echo "\nJust a little prayer so we know we are allright.\n\n";

echo $this->getPrayer();
}
}

/**
* Outputs results as a JSON string
*
* @param boolean $allSucceeded Have all tests been successful
*/
private function writeJson(bool $allSucceeded)
{
header('Content-Type: application/json; charset=utf-8');

$tests = [];
foreach ($this->testsData as $data) {
$tests[] = [
'order' => $data['order'],
'duration' => sprintf("%.6f s", $data['duration']),
'ident' => $data['ident'],
'result' => $data['result']->getStatusMessage(),
'test_description' => $data['test']->getDescription(),
'result_description' => $data['result']->getDescription(),
];
}

$data = [
'included' => $this->includeFilter,
'excluded' => $this->excludeFilter,
'tests' => $tests,
'urls' => [
'text' => '?' . self::PARAM_INCLUDE . '=' . $this->includeFilter
. '&amp;' . self::PARAM_EXCLUDE . '=' . $this->excludeFilter
. '&amp;' . self::PARAM_OUTPUT . '=' . self::OUTPUT_TEXT,
'html' => '?' . self::PARAM_INCLUDE . '=' . $this->includeFilter
. '&amp;' . self::PARAM_EXCLUDE . '=' . $this->excludeFilter
. '&amp;' . self::PARAM_OUTPUT . '=' . self::OUTPUT_HTML,
]
];

if ($allSucceeded) {
$data['prayer'] = $this->getPrayer();
}

echo json_encode($data);
}

private function getPrayer(): string
{
$return = '';
for ($i = 0; $i < 5; $i++) {
$return .= 'Our Father in heaven,' . "\n";
$return .= 'hallowed be your name,' . "\n";
$return .= 'your kingdom come,' . "\n";
$return .= 'your will be done' . "\n";
$return .= 'on earth as it is in heaven.' . "\n";
$return .= 'Give us today our daily bread,' . "\n";
$return .= 'and forgive us the wrong we have done' . "\n";
$return .= 'as we forgive those who wrong us.' . "\n";
$return .= 'Subject us not to the trial' . "\n";
$return .= 'but deliver us from the evil one.' . "\n";
$return .= 'And make the ' . $this->project . " project work.\n";
$return .= 'Amen.' . "\n\n";
}

return $return;
}

}
92 changes: 92 additions & 0 deletions Jyxo/Beholder/Output/HtmlOutput.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php declare(strict_types = 1);

/**
* Jyxo PHP Library
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file license.txt.
* It is also available through the world-wide-web at this URL:
* https://github.com/jyxo/php/blob/master/license.txt
*/

namespace Jyxo\Beholder\Output;

use Jyxo\Beholder\Executor;

/**
* Beholder HTML output class
*
* @category Jyxo
* @package Jyxo\Beholder
* @author Matěj Humpál
*/
class HtmlOutput extends \Jyxo\Beholder\Output\Output
{

public function getContentType(): string
{
return 'text/html; charset=utf-8';
}

public function __toString(): string
{
$return = '';

$return .= '<head>' . "\n";
$return .= '<meta http-equiv="content-type" content="text/html; charset=utf-8" />' . "\n";
$return .= '<title>Beholder for project ' . $this->result->getProject() . '</title>' . "\n";
$return .= '<style>' . "\n";
$return .= ' body {font: 12px Verdana, Geneva, Arial, Helvetica, sans-serif;}' . "\n";
$return .= ' table {font-size: small; border-collapse: collapse;}' . "\n";
$return .= ' table th {border: 1px solid #000; background: #000; color: #fff;}' . "\n";
$return .= ' table td {border: 1px solid #000; padding: .25em .5em;}' . "\n";
$return .= '</style>' . "\n";
$return .= '</head>' . "\n";
$return .= '<body style="background-color: ' . ($this->result->hasAllSucceeded() ? '#ccffcc' : '#ffcccc') . '; width: 90%; height: 100%; padding: 1em; margin: 0;">' . "\n";
$return .= '<h1>Beholder for project ' . $this->result->getProject() . "</h1>\n";
$return .= '<p>Tests included: ' . $this->result->getIncludeFilter() . "\n";
$return .= '<br>Tests excluded: ' . $this->result->getExcludeFilter() . "\n";
$return .= '</p>' . "\n";
$return .= '<table><tr><th>Run order</th><th>Duration</th><th>Ident</th><th>Status</th><th>Test name</th><th>Comment</th></tr>' . "\n";
foreach ($this->result->getTestsData() as $data) {
$return .= sprintf('
<tr>
<td>%d</td>
<td>%.2fs</td>
<td>%s</td>
<td style="color: %s;">%s</td>
<td><b>%s</b></td>
<td><i>%s</i></td>
</tr>' . "\n",
$data['order'],
$data['duration'],
$data['ident'],
$data['result']->isSuccess() ? 'green' : 'red; font-weight: bold;', $data['result']->getStatusMessage(),
$data['test']->getDescription(),
$data['result']->getDescription()
);
}
$return .= '</table>
<h2>Parameters</h2>
<dl>
<dt>' . Executor::PARAM_INCLUDE . '</dt>
<dd>Tests to include, list of shell patterns separated by comma, default *</dd>
<dt>' . Executor::PARAM_EXCLUDE . '</dt>
<dd>Tests to exclude, empty by default</dd>
<dt>' . Executor::PARAM_OUTPUT . '</dt>
<dd>' . Executor::OUTPUT_HTML . ' = HTML output, ' . Executor::OUTPUT_TEXT . ' = text output, ' . Executor::OUTPUT_JSON . ' = JSON output</dd>
</dl>
<p>Tests are included, then excluded.</p>
<p><a href="?' . Executor::PARAM_INCLUDE . '=' . $this->result->getIncludeFilter()
. '&amp;' . Executor::PARAM_EXCLUDE . '=' . $this->result->getExcludeFilter()
. '&amp;' . Executor::PARAM_OUTPUT . '=' . Executor::OUTPUT_TEXT . '">Text version</a></p>
<p><a href="?' . Executor::PARAM_INCLUDE . '=' . $this->result->getIncludeFilter()
. '&amp;' . Executor::PARAM_EXCLUDE . '=' . $this->result->getExcludeFilter()
. '&amp;' . Executor::PARAM_OUTPUT . '=' . Executor::OUTPUT_JSON . '">JSON version</a></p>
</body>' . "\n";

return $return;
}
}
Loading

0 comments on commit b08b902

Please sign in to comment.