{"action":"created","issue":{"url":"https://api.github.com/repos/sebastianbergmann/phpunit/issues/1793","labels_url":"https://api.github.com/repos/sebastianbergmann/phpunit/issues/1793/labels{/name}","comments_url":"https://api.github.com/repos/sebastianbergmann/phpunit/issues/1793/comments","events_url":"https://api.github.com/repos/sebastianbergmann/phpunit/issues/1793/events","html_url":"https://github.com/sebastianbergmann/phpunit/pull/1793","id":95304979,"number":1793,"title":"Add support for expectations","user":{"login":"ircmaxell","id":660654,"avatar_url":"https://avatars.githubusercontent.com/u/660654?v=3","gravatar_id":"","url":"https://api.github.com/users/ircmaxell","html_url":"https://github.com/ircmaxell","followers_url":"https://api.github.com/users/ircmaxell/followers","following_url":"https://api.github.com/users/ircmaxell/following{/other_user}","gists_url":"https://api.github.com/users/ircmaxell/gists{/gist_id}","starred_url":"https://api.github.com/users/ircmaxell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ircmaxell/subscriptions","organizations_url":"https://api.github.com/users/ircmaxell/orgs","repos_url":"https://api.github.com/users/ircmaxell/repos","events_url":"https://api.github.com/users/ircmaxell/events{/privacy}","received_events_url":"https://api.github.com/users/ircmaxell/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":9,"created_at":"2015-07-15T22:34:31Z","updated_at":"2015-12-07T15:06:25Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/sebastianbergmann/phpunit/pulls/1793","html_url":"https://github.com/sebastianbergmann/phpunit/pull/1793","diff_url":"https://github.com/sebastianbergmann/phpunit/pull/1793.diff","patch_url":"https://github.com/sebastianbergmann/phpunit/pull/1793.patch"},"body":"**NOTE**: This is not a production PR, but should be used as a point-of-reference for the discussion of `expect*` additions.\r\n\r\n## What are expectations\r\nQuite simply, expectations are assertions that don't immediately fail tests. They can accumulate over the execution of a test.\r\n\r\n## Why?\r\nExpectations provide the ability to get richer and more complete failure data.\r\n\r\n## How it works:\r\nSimply replace \"assert\" with \"expect\" in any valid assertion call. The rest is handled by the framework. Instead of a failure halting the test (as with an assertion), expectations keep executing.\r\n\r\n**For the proof-of-concept** expectation errors are only displayed if there was no other assertion failure. This should be fixed in the future.\r\n\r\n## When would I use expect instead of assert:\r\nIn short, if a failure in one place means you can't get any meaningful data out of the rest of the failures, then use assert. Otherwise use expect.\r\n\r\nExample:\r\n\r\n    public function testFoo() {\r\n        $array = foo();\r\n        // This is an assertion, because the rest of the test makes no sense without it\r\n        $this->assertTrue(is_array($array), \"The return value is an array\");\r\n        $this->expectEquals(\"test\", $array[0]);\r\n        $this->expectEquals(123, $array['test']);\r\n       // etc\r\n    }\r\n\r\nThe first is an assertion, because continuing the test may be dangerous. The rest are expectations because if one fails, it means nothing to the others. So by using expectations, you get more complete failure information.\r\n\r\n## Output:\r\nThe POC will generate for the following code:\r\n\r\n    public function testExpectEqualsFailure() \r\n    {\r\n        $this->expectEquals(1, 2);\r\n        $this->expectEquals(2, 3);\r\n    }  \r\n\r\nThe following failure:\r\n\r\n    There was 1 failure:\r\n\r\n    1) Framework_ExpectTest::testExpectEqualsFailure\r\n    Failed Expectations\r\n    0: Failed asserting that 2 matches expected 1.\r\n\r\n        src/Framework/Constraint/IsEqual.php:134\r\n        src/Framework/Assert.php:1934\r\n        src/Framework/Assert.php:486\r\n        src/Framework/Expect.php:24\r\n        tests/Framework/ExpectTest.php:34\r\n        src/Framework/TestCase.php:888\r\n        src/Framework/TestCase.php:747\r\n        src/Framework/TestResult.php:601\r\n        src/Framework/TestCase.php:703\r\n        src/Framework/TestSuite.php:735\r\n        src/Framework/TestSuite.php:735\r\n        src/Framework/TestSuite.php:735\r\n        src/TextUI/TestRunner.php:429\r\n        src/TextUI/Command.php:149\r\n        src/TextUI/Command.php:101\r\n\r\n    1: Failed asserting that 3 matches expected 2.\r\n\r\n        src/Framework/Constraint/IsEqual.php:134\r\n        src/Framework/Assert.php:1934\r\n        src/Framework/Assert.php:486\r\n        src/Framework/Expect.php:24\r\n        tests/Framework/ExpectTest.php:35\r\n        src/Framework/TestCase.php:888\r\n        src/Framework/TestCase.php:747\r\n        src/Framework/TestResult.php:601\r\n        src/Framework/TestCase.php:703\r\n        src/Framework/TestSuite.php:735\r\n        src/Framework/TestSuite.php:735\r\n        src/Framework/TestSuite.php:735\r\n        src/TextUI/TestRunner.php:429\r\n        src/TextUI/Command.php:149\r\n        src/TextUI/Command.php:101\r\n\r\n        src/Framework/TestCase.php:754\r\n        src/Framework/TestResult.php:601\r\n        src/Framework/TestCase.php:703\r\n        src/Framework/TestSuite.php:735\r\n        src/Framework/TestSuite.php:735\r\n        src/Framework/TestSuite.php:735\r\n        src/TextUI/TestRunner.php:429\r\n        src/TextUI/Command.php:149\r\n        src/TextUI/Command.php:101\r\n\r\n    --\r\n\r\n\r\n## Real World\r\nThe very test included in this pull request uses expectations.\r\n\r\n    public function testExpectEquals()\r\n    {\r\n        try {\r\n            $this->expectEquals(1, 2);\r\n            $this->expectEquals(2, 3);\r\n        } catch (Exception $e) {\r\n            $this->fail(\"No exceptions should be thrown!!!\");\r\n        }\r\n        $expectations = self::getFailedExpectations();\r\n        self::resetFailedExpectations();\r\n        $this->assertCount(2, $expectations);\r\n        $this->expectEquals(\"Failed asserting that 2 matches expected 1.\", $expectations[0]->toString());\r\n        $this->expectEquals(\"Failed asserting that 3 matches expected 2.\", $expectations[1]->toString());\r\n    }\r\n\r\nIn this case, we're asserting that there were 2 failed expectations, but then expecting each individual message.\r\n\r\nPHPUnit's own test suite has areas where this could be used:\r\n\r\n    /**\r\n     * @covers PHPUnit_Framework_Assert::assertArraySubset\r\n     * @covers PHPUnit_Framework_Constraint_ArraySubset\r\n     */\r\n    public function testassertArraySubset()\r\n    {\r\n        $array = [\r\n            'a' => 'item a',\r\n            'b' => 'item b',\r\n            'c' => ['a2' => 'item a2', 'b2' => 'item b2'],\r\n            'd' => ['a2' => ['a3' => 'item a3', 'b3' => 'item b3']]\r\n        ];\r\n\r\n        $this->assertArraySubset(['a' => 'item a', 'c' => ['a2' => 'item a2']], $array);\r\n        $this->assertArraySubset(['a' => 'item a', 'd' => ['a2' => ['b3' => 'item b3']]], $array);\r\n\r\n        try {\r\n            $this->assertArraySubset(['a' => 'bad value'], $array);\r\n        } catch (PHPUnit_Framework_AssertionFailedError $e) {\r\n        }\r\n\r\n        try {\r\n            $this->assertArraySubset(['d' => ['a2' => ['bad index' => 'item b3']]], $array);\r\n        } catch (PHPUnit_Framework_AssertionFailedError $e) {\r\n            return;\r\n        }\r\n\r\n        $this->fail();\r\n    }\r\n\r\nIn this case, the first 2 `assertArraySubset` calls could/should be `expect` calls.\r\n\r\n## Next steps\r\nThis is just a dirty proof-of-concept to frame the discussion. Check this PR out, try it and see the behavior. And discuss."},"comment":{"url":"https://api.github.com/repos/sebastianbergmann/phpunit/issues/comments/162550355","html_url":"https://github.com/sebastianbergmann/phpunit/pull/1793#issuecomment-162550355","issue_url":"https://api.github.com/repos/sebastianbergmann/phpunit/issues/1793","id":162550355,"user":{"login":"sebastianbergmann","id":25218,"avatar_url":"https://avatars.githubusercontent.com/u/25218?v=3","gravatar_id":"","url":"https://api.github.com/users/sebastianbergmann","html_url":"https://github.com/sebastianbergmann","followers_url":"https://api.github.com/users/sebastianbergmann/followers","following_url":"https://api.github.com/users/sebastianbergmann/following{/other_user}","gists_url":"https://api.github.com/users/sebastianbergmann/gists{/gist_id}","starred_url":"https://api.github.com/users/sebastianbergmann/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sebastianbergmann/subscriptions","organizations_url":"https://api.github.com/users/sebastianbergmann/orgs","repos_url":"https://api.github.com/users/sebastianbergmann/repos","events_url":"https://api.github.com/users/sebastianbergmann/events{/privacy}","received_events_url":"https://api.github.com/users/sebastianbergmann/received_events","type":"User","site_admin":false},"created_at":"2015-12-07T15:06:25Z","updated_at":"2015-12-07T15:06:25Z","body":"@keradus PHPUnit 4.8 is bug fixes only."}}