4 * Use this trait to check that code run by tests accesses every key declared for this class'
5 * ServiceOptions, e.g., in a $constructorOptions member variable. To use this trait, you need to do
6 * two things (other than use-ing it):
8 * 1) Don't use the regular ServiceOptions when constructing your objects, but rather
9 * LoggedServiceOptions. These are used the same as ServiceOptions, except in the constructor, pass
10 * self::$serviceOptionsAccessLog before the regular arguments.
12 * 2) Make a test that calls assertAllServiceOptionsUsed(). If some ServiceOptions keys are not yet
13 * accessed in tests but actually are used by the class, pass their names as an argument.
15 * Currently we support only one ServiceOptions per test class.
17 trait TestAllServiceOptionsUsed
{
18 /** @var array [ expected keys (as list), keys accessed so far (as dictionary) ] */
19 private static $serviceOptionsAccessLog = [];
22 * @param string[] $expectedUnused Options that we know are not yet tested
24 public function assertAllServiceOptionsUsed( array $expectedUnused = [] ) {
25 $this->assertNotEmpty( self
::$serviceOptionsAccessLog,
26 'You need to pass LoggedServiceOptions to your class instead of ServiceOptions ' .
27 'for TestAllServiceOptionsUsed to work.'
30 list( $expected, $actual ) = self
::$serviceOptionsAccessLog;
32 $expected = array_diff( $expected, $expectedUnused );
36 array_diff( $expected, array_keys( $actual ) ),
37 "Some ServiceOptions keys were not accessed in tests. If they really aren't used, " .
38 "remove them from the class' option list. If they are used, add tests to cover them, " .
39 "or ignore the problem for now by passing them to assertAllServiceOptionsUsed() in " .
40 "its \$expectedUnused argument."
43 if ( $expectedUnused ) {
44 $this->markTestIncomplete( 'Some ServiceOptions keys are not yet accessed by tests: ' .
45 implode( ', ', $expectedUnused ) );