*/ private static array $tests = array(); /** * Suite currently being loaded. * * @var string */ public static string $suite = ''; /** * Register a test. * * `xfail` marks a known bug: a failure is reported as XFAIL (not counted), * a pass is reported as XPASS and counted as a failure so the marker gets * removed by the PR that fixes the bug. * * @param string $name Test name. * @param callable $fn Test body. * @param array $opts Options: xfail => reason. */ public static function test( string $name, callable $fn, array $opts = array() ): void { self::$tests[] = array( 'suite' => self::$suite, 'name' => $name, 'fn' => $fn, 'xfail' => (string) ( $opts['xfail'] ?? '' ), ); } /** * Run every registered test; return true when nothing failed. */ public static function run(): bool { $counts = array( 'PASS' => 0, 'FAIL' => 0, 'XFAIL' => 0, 'XPASS' => 0, 'SKIP' => 0 ); foreach ( self::$tests as $t ) { $detail = ''; try { ( $t['fn'] )(); $status = '' !== $t['xfail'] ? 'XPASS' : 'PASS'; } catch ( TMDO_Live_Skip $e ) { $status = 'SKIP'; $detail = $e->getMessage(); } catch ( Throwable $e ) { $status = '' !== $t['xfail'] ? 'XFAIL' : 'FAIL'; $detail = ( $e instanceof TMDO_Live_Failure ? '' : get_class( $e ) . ': ' ) . $e->getMessage(); } finally { TMDO_Live_Fixtures::teardown(); } ++$counts[ $status ]; if ( '' !== $t['xfail'] ) { $detail = trim( $detail . ' [xfail: ' . $t['xfail'] . ']' ); } printf( "%-5s %s :: %s%s\n", $status, $t['suite'], $t['name'], '' !== $detail ? "\n " . $detail : '' ); } printf( "\n%d passed, %d failed, %d xfail, %d xpass, %d skipped\n", $counts['PASS'], $counts['FAIL'], $counts['XFAIL'], $counts['XPASS'], $counts['SKIP'] ); return 0 === $counts['FAIL'] && 0 === $counts['XPASS']; } } /** * Fail unless $actual is identical to $expected. * * @param mixed $expected Expected value. * @param mixed $actual Actual value. * @param string $message Context. */ function tmdo_live_assert_same( $expected, $actual, string $message ): void { if ( $expected !== $actual ) { throw new TMDO_Live_Failure( sprintf( '%s — expected %s, got %s', $message, var_export( $expected, true ), var_export( $actual, true ) ) // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export ); } } /** * Fail unless $condition is true. * * @param bool $condition Condition. * @param string $message Context. */ function tmdo_live_assert_true( bool $condition, string $message ): void { if ( ! $condition ) { throw new TMDO_Live_Failure( $message ); } }