Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ dependencies:

test:
override:
- docker run -v "$(pwd)":"$(pwd)" --workdir="$(pwd)" -e "CIRCLE_TEST_REPORTS=$CIRCLE_TEST_REPORTS" hhvm/hhvm:3.15-lts-latest hhvm -c test/self-test.ini test/self-test.php
- docker run -v "$(pwd)":"$(pwd)" -v "$CIRCLE_TEST_REPORTS":"$CIRCLE_TEST_REPORTS" --workdir="$(pwd)" -e "CIRCLE_TEST_REPORTS=$CIRCLE_TEST_REPORTS" hhvm/hhvm:3.15-lts-latest hhvm -c test/self-test.ini test/self-test.php
15 changes: 15 additions & 0 deletions src/Assert.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,19 @@ public function skip(
$l($skip);
}
}

public function fail(string $message): void {
$stack = Util\Trace::generate();
$traceItem = shape(
'file' => $stack[0]['file'],
'line' => $stack[0]['line'],
'function' => $stack[1]['function'],
'class' => $stack[1]['class'],
);
$fail =
new Event\Failure($message, $traceItem, Util\Trace::findTestMethod());
foreach ($this->failureListeners as $l) {
$l($fail);
}
}
}
7 changes: 4 additions & 3 deletions src/Contract/Assert.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ public function mixed(mixed $context): Assertion\MixedAssertion;
public function container<T>(
Container<T> $context,
): Assertion\ContainerAssertion<T>;
public function keyedContainer<Tkey,Tval>(
KeyedContainer<Tkey,Tval> $context,
): Assertion\KeyedContainerAssertion<Tkey,Tval>;
public function keyedContainer<Tkey, Tval>(
KeyedContainer<Tkey, Tval> $context,
): Assertion\KeyedContainerAssertion<Tkey, Tval>;
public function skip(string $reason, ?TraceItem $traceItem = null): void;
public function fail(string $reason): void;
}
2 changes: 2 additions & 0 deletions src/Contract/Test/Suite.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

use HackPack\HackUnit\Contract\Assert;
use HackPack\HackUnit\Event\TestStartListener;
use HackPack\HackUnit\Event\TestEndListener;

interface Suite {
public function up(): Awaitable<void>;
public function run(
Assert $assert,
(function(): void) $testPassed,
\ConstVector<TestStartListener> $testStartListeners,
\ConstVector<TestEndListener> $testEndListeners,
): Awaitable<void>;
public function down(): Awaitable<void>;
public function name(): string;
Expand Down
3 changes: 2 additions & 1 deletion src/Event/Listeners.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
type RunStartListener = (function(): void);
type SkipListener = (function(Skip): void);
type SuccessListener = (function(Success): void);
type SuiteEndListener = (function(): void);
type SuiteEndListener = (function(SuiteEnd): void);
type SuiteStartListener = (function(SuiteStart): void);
type TestEndListener = (function(TestEnd): void);
type TestStartListener = (function(TestStart): void);
11 changes: 11 additions & 0 deletions src/Event/SuiteEnd.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?hh // strict

namespace HackPack\HackUnit\Event;

class SuiteEnd {
public function __construct(private string $suiteName) {}

public function suiteName(): string {
return $this->suiteName;
}
}
28 changes: 28 additions & 0 deletions src/Event/TestEnd.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?hh // strict

namespace HackPack\HackUnit\Event;

final class TestEnd {
public function __construct(
private string $suiteName,
private string $testName,
private ?string $file,
private ?int $line,
) {}

public function suiteName(): string {
return $this->suiteName;
}

public function testName(): string {
return $this->testName;
}

public function file(): string {
return $this->file === null ? '??' : $this->file;
}

public function line(): int {
return $this->line === null ? -1 : $this->line;
}
}
10 changes: 10 additions & 0 deletions src/Event/TestStart.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class TestStart {
public function __construct(
private string $suiteName,
private string $testName,
private ?string $file,
private ?int $line,
) {}

public function suiteName(): string {
Expand All @@ -15,4 +17,12 @@ public function suiteName(): string {
public function testName(): string {
return $this->testName;
}

public function file(): string {
return $this->file === null ? '??' : $this->file;
}

public function line(): int {
return $this->line === null ? -1 : $this->line;
}
}
11 changes: 9 additions & 2 deletions src/HackUnit.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,16 @@ public function run(): void {
$this->runner->onRunStart(
() ==> {
$this->status->handleRunStart();
$this->summaryBuilder->startTiming();
$this->summaryBuilder->handleRunStart();
},
);

$this->runner->onTestStart(
($e) ==> {
$this->summaryBuilder->handleTestStart($e);
},
);

$this->runner->onFailure(
($e) ==> {
// Allow us to set the exit code
Expand Down Expand Up @@ -70,7 +77,7 @@ public function run(): void {
);
$this->runner->onRunEnd(
() ==> {
$this->summaryBuilder->stopTiming();
$this->summaryBuilder->handleRunEnd();
$summary = $this->summaryBuilder->getSummary();
foreach ($this->reportFormatters as $formatter) {
$formatter->writeReport($summary);
Expand Down
78 changes: 78 additions & 0 deletions src/Report/Format/JUnit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?hh // strict

namespace HackPack\HackUnit\Report\Format;

use HackPack\HackUnit\Report\Format;
use HackPack\HackUnit\Report\Summary;
use HackPack\HackUnit\Report\TestResult;
use HackPack\HackUnit\Report\TestSummary;
use HackPack\HackUnit\Report\SuiteSummary;
use SimpleXMLElement;

final class JUnit implements Format {
private SimpleXMLElement $report;

public static function build(string $reportPath): this {
return new self(fopen($reportPath, 'w'));
}

public function __construct(private resource $out) {
$this->report = new SimpleXMLElement('<testsuites/>');
}

public function writeReport(Summary $summary): void {
foreach ($summary['suite summaries'] as $name => $suiteSummary) {
$this->report->addChild('testsuite')
|> $this->populateSuiteReport($name, $suiteSummary, $$);
}
fwrite($this->out, $this->report->asXML());
}

private function populateSuiteReport(
string $name,
SuiteSummary $summary,
SimpleXMLElement $report,
): void {
$report->addAttribute('name', $name);
$this->addSuiteCounts($summary, $report);
foreach ($summary['test summaries'] as $testName => $testSummary) {
$report->addChild('testcase')
|> $this->populateTestReport($name, $testName, $testSummary, $$);
}
}

private function addSuiteCounts(
SuiteSummary $summary,
SimpleXMLElement $report,
): void {
$report->addAttribute('failures', $summary['fail count']);
$report->addAttribute('tests', $summary['test count']);
}

private function populateTestReport(
string $suiteName,
string $name,
TestSummary $summary,
SimpleXMLElement $report,
): void {
$report->addAttribute('name', $name);
$report->addAttribute('classname', $suiteName);

switch ($summary['result']) {
case TestResult::Pass:
case TestResult::Error:
// Error is not used yet
// Nothing more to add when test passes
break;
case TestResult::Fail:
$event = $summary['fail event'];
$message = $event === null ? 'Unknown failure' : $event->getMessage();
$failElement = $report->addChild('failure');
$failElement->addAttribute('message', $message);
break;
case TestResult::Skip:
$report->addChild('skip');
break;
}
}
}
Loading