0

I'm extending Laravel's base TestCase class to include my own assertion. Something like this:

<?php

namespace Tests\Mine;

use Tests\TestCase;

class SomeTest extends TestCase {
    public function testSomethingIsWorking(): void {
        $this->assertSomething("foo", "bar");
    }
}
<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

class TestCase extends BaseTestCase {
    public function assertSomething($foo, $bar): void {
        $this->assertSomethingElse($foo, $bar);
    }

    public function assertSomethingElse($foo, $bar): void {
        if ($foo !== $bar) {
            $this->fail("Some message here");
        }
    }
}

This works fine, but when I run artisan test, a failure is triggered it shows the context of TestCase::assertSomethingElse(). So I don't get to see where in the test the failure occurs; the output looks something like this:

FAILED Tests\Mine > something is working                    AssertionFailedError
Some message here

at tests/TestCase.php:10

  9  |        if ($foo !== bar)
➜ 10 |            $this->fail("Some message here");
  11 |        }

1   tests/TestCase.php:10
2   tests/TestCase.php:5

This is Laravel-specific behaviour; if I just run vendor/bin/phpunit no context is shown, and the stack trace does go back as far as the original test.

Is there a way I can get artisan test to show the contextual lines from SomeTest::testSomethingIsWorking() instead? Failing that, is there some way I can at least get the stack trace at the bottom to go back to the original test?

miken32
  • 42,008
  • 16
  • 111
  • 154
  • Could be just an issue with the test-reporter (artisan test), you could try to make the TestCase class abstract. Also $this->fail() might be fishy, perhaps better use an assertion $this->assertTrue(false, $message) but not sure. always work with $message when you stabiliize your assertions. – hakre Jul 24 '23 at 18:52
  • I did try getting rid of the call to `fail()` in the `assertSomethingElse()` method with no change. I do want to output the message from the original assertion failure so can't replace it in the `assertSomething()` method – miken32 Jul 25 '23 at 19:22

1 Answers1

0

Made some progress with the following changes:

<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

class TestCase extends BaseTestCase {
    public function assertSomething($foo, $bar): void {
        // wrap the assertion in a try
        try {
            $this->assertSomethingElse($foo, $bar);
        } catch (Throwable $e) {
            $this->fail($e->getMessage());
        }
    }

    public function assertSomethingElse($foo, $bar): void {
        if ($foo !== $bar) {
            $this->fail("Some message here");
        }
    }
}

Which is ugly but at least provides a stack trace leading back to the test as desired:

1   tests/TestCase.php:12
2   tests/Mine/SomeTest.php:8

Test output is handled in Laravel by the nunomaduro/collision package which I'm just trying to figure out now.

miken32
  • 42,008
  • 16
  • 111
  • 154