phpunit

Updated: 02 November 2023

Filter

For annotated test methods

/**
 * @group regression
 * @group bug2204
 */
public function testSomethingElse(): void
{
}
docker compose exec symfony bin/phpunit --group bug2204

Run all tests in one test class

bin/phpunit --testdox --filter ProposalControllerTest

Run specific scenarios

Updated: 04 February 2023

SpecFlow converts tags in feature files to test case categories.

For xUnit

dotnet test --filter Category=done
dotnet test --filter "Category=us123 & Category=done"
dotnet test --filter "Category=done | Category=automated"
@US123
Feature: Breakfast

@done @important
Scenario: Eating cucumbers
  Given there are 12 cucumbers
  When I eat 5 cucumbers
  Then I should have 7 cucumbers

@automated
Scenario: Use all the sugar
  Given there is some sugar in the cup
  When I put all the sugar to my coffee
  Then the cup is empty

https://docs.specflow.org/projects/specflow/en/latest/Execution/Executing-Specific-Scenarios.html

Behaviour Driven Development

Updated: 02 February 2023

Feature file

The purpose of a feature file is to document the expected behaviour of an application in a way that it is both human-readable and suitable for test automation. A feature file contains Scenarios, expressed in the Gherkin syntax i.e. Given / When / Then steps.

Given ~ Arrange
When ~ Act
Then ~ Assert

Testing

Updated: 30 March 2021

Unit Tests

phpunit & phpspec

This type of testing calls methods of an object. Test doubles are used in place of all but the simplest object dependencies of the class under test.

Integration Tests

phpunit

This type of testing calls methods on an object. Unlike unit testing, the real object dependencies of the class under test are used.

Functional Tests

phpunit & behat

This type of testing does not call the methods of an object directly. Instead, functional testing involves writing code which commands a http client or browser. The general cycle:

  1. Make a request.
  2. Click on a link or submit a form.
  3. Test the response.
  4. Reset fixtures and repeat.

Can also test an http API response.

Prophecy

Updated: 17 September 2022

Dummy

$dummy = $this->prophesize(SomeClass::class);
$sut->action($dummy->reveal());

// with phpspec
class MarkdownSpec extends ObjectBehavior
{
    function it_converts_text_from_an_external_source(Reader $reader)
    {
        // $reader is a Dummy at this point because we've added
        // no behaviour nor made any assertions on its methods.
    }
}

Stub

$stub = $this->prophesize(SomeClass::class);
$stub->getSomething()->willReturn('foo');
$sut->action($stub->reveal());

// with phpspec
class MarkdownSpec extends ObjectBehavior
{
    function it_converts_text_from_an_external_source(Reader $reader)
    {
        $reader->getMarkdown()->willReturn("Hi, there");

        // $reader is now a Stub because we are controlling its behaviour.

        $this->toHtmlFromReader($reader)->shouldReturn("Hi, there");
    }
}

Mock

$mock = $this->prophesize(SomeClass::class);
$mock->doSomething('bar')->shouldBeCalled();
$sut->action($mock->reveal());

// with phpspec
class MarkdownSpec extends ObjectBehavior
{
    function it_outputs_converted_text(Writer $writer)
    {
        $writer->writeText("Hi, there")->shouldBeCalled();

        // Adding an assertion before the double is used makes it a Mock.

        $this->outputHtml("Hi, there", $writer);
    }
}

Spy

$spy = $this->prophesize(SomeClass::class);
$sut->action($spy->reveal());
$spy->doSomething('bar')->shouldHaveBeenCalled();

// with phpspec
class MarkdownSpec extends ObjectBehavior
{
    function it_outputs_converted_text(Writer $writer)
    {
        $this->outputHtml("Hi, there", $writer);

        // Adding an expectation after the double is used makes it a Spy.
        $writer->writeText("Hi, there")->shouldHaveBeenCalled();
    }
}