PhpUnitAttributesFixerTest.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of PHP CS Fixer.
  5. *
  6. * (c) Fabien Potencier <fabien@symfony.com>
  7. * Dariusz Rumiński <dariusz.ruminski@gmail.com>
  8. *
  9. * This source file is subject to the MIT license that is bundled
  10. * with this source code in the file LICENSE.
  11. */
  12. namespace PhpCsFixer\Tests\Fixer\PhpUnit;
  13. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  14. /**
  15. * @internal
  16. *
  17. * @covers \PhpCsFixer\Fixer\PhpUnit\PhpUnitAttributesFixer
  18. *
  19. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\PhpUnit\PhpUnitAttributesFixer>
  20. *
  21. * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\PhpUnit\PhpUnitAttributesFixer
  22. */
  23. final class PhpUnitAttributesFixerTest extends AbstractFixerTestCase
  24. {
  25. /**
  26. * @requires PHP 8.0
  27. *
  28. * @dataProvider provideFixCases
  29. *
  30. * @param _AutogeneratedInputConfiguration $configuration
  31. */
  32. public function testFix(string $expected, ?string $input = null, array $configuration = []): void
  33. {
  34. $this->fixer->configure($configuration);
  35. $this->doTest($expected, $input);
  36. }
  37. /**
  38. * @return iterable<array{0: string, 1?: string}>
  39. */
  40. public static function provideFixCases(): iterable
  41. {
  42. yield 'do not fix with wrong values' => [<<<'PHP'
  43. <?php
  44. /**
  45. * @requires
  46. * @uses
  47. */
  48. class FooTest extends \PHPUnit\Framework\TestCase {
  49. /**
  50. * @backupGlobals
  51. * @backupStaticAttributes
  52. * @covers
  53. * @dataProvider
  54. * @depends
  55. * @group
  56. * @preserveGlobalState
  57. * @testDox
  58. * @testWith
  59. * @ticket
  60. */
  61. public function testFoo() { self::assertTrue(true); }
  62. }
  63. PHP];
  64. yield 'do not fix with wrong casing' => [<<<'PHP'
  65. <?php
  66. /**
  67. * @COVERS \Foo
  68. */
  69. class FooTest extends \PHPUnit\Framework\TestCase {
  70. /**
  71. * @dataPROVIDER provideFooCases
  72. * @requires php 8.3
  73. */
  74. public function testFoo() { self::assertTrue(true); }
  75. }
  76. PHP];
  77. yield 'do not fix when not supported by attributes' => [<<<'PHP'
  78. <?php
  79. /**
  80. * @covers FooClass::FooMethod
  81. * @uses ClassName::methodName
  82. */
  83. class FooTest extends \PHPUnit\Framework\TestCase {
  84. public function testFoo() { self::assertTrue(true); }
  85. }
  86. PHP];
  87. yield 'do not fix when there is already attribute of related class' => [<<<'PHP'
  88. <?php
  89. class FooTest extends \PHPUnit\Framework\TestCase {
  90. /**
  91. * @requires PHP ^8.2
  92. */
  93. #[\FirstAttributeToMakeSureMultipleAttributesWorks]
  94. #[\PHPUnit\Framework\Attributes\RequiresPhp('^7.1')]
  95. #[\ThirdAttributeToMakeSureMultipleAttributesWorks]
  96. public function testFoo() {}
  97. }
  98. PHP];
  99. yield 'do not duplicate attribute when used without leading slash' => [<<<'PHP'
  100. <?php
  101. class FooTest extends \PHPUnit\Framework\TestCase {
  102. /**
  103. * @requires PHP ^6.1
  104. */
  105. #[PHPUnit\Framework\Attributes\RequiresPhp('^6.1')]
  106. public function testFoo() {}
  107. }
  108. PHP];
  109. yield 'do not duplicate attribute when used with import' => [<<<'PHP'
  110. <?php
  111. use PHPUnit\Framework\Attributes\RequiresPhp;
  112. class FooTest extends \PHPUnit\Framework\TestCase {
  113. /**
  114. * @requires PHP ^6.2
  115. */
  116. #[RequiresPhp('^6.2')]
  117. public function testFoo() {}
  118. }
  119. PHP];
  120. yield 'do not duplicate attribute when used with partial import' => [<<<'PHP'
  121. <?php
  122. use PHPUnit\Framework\Attributes;
  123. class FooTest extends \PHPUnit\Framework\TestCase {
  124. /**
  125. * @requires PHP ^6.2
  126. */
  127. #[Attributes\RequiresPhp('^6.2')]
  128. public function testFoo() {}
  129. }
  130. PHP];
  131. yield 'do not duplicate attribute when used with alias' => [<<<'PHP'
  132. <?php
  133. use PHPUnit\Framework\Attributes\RequiresPhp as PHPUnitRequiresPhp;
  134. class FooTest extends \PHPUnit\Framework\TestCase {
  135. /**
  136. * @requires PHP ^6.0
  137. */
  138. #[PHPUnitRequiresPhp('^6.0')]
  139. public function testFoo() {}
  140. }
  141. PHP];
  142. yield 'do not duplicate attribute when used with partial alias' => [<<<'PHP'
  143. <?php
  144. use PHPUnit\Framework\Attributes as PHPUnitAttributes;
  145. class FooTest extends \PHPUnit\Framework\TestCase {
  146. /**
  147. * @requires PHP ^6.0
  148. */
  149. #[PHPUnitAttributes\RequiresPhp('^6.0')]
  150. public function testFoo() {}
  151. }
  152. PHP];
  153. yield 'fix multiple annotations' => [
  154. <<<'PHP'
  155. <?php
  156. class FooTest extends \PHPUnit\Framework\TestCase {
  157. /**
  158. * @copyright ACME Corporation
  159. */
  160. #[\PHPUnit\Framework\Attributes\DataProvider('provideFooCases')]
  161. #[\PHPUnit\Framework\Attributes\RequiresPhp('^8.2')]
  162. #[\PHPUnit\Framework\Attributes\RequiresOperatingSystem('Linux|Darwin')]
  163. public function testFoo($x) { self::assertTrue($x); }
  164. public static function provideFooCases() { yield [true]; yield [false]; }
  165. }
  166. PHP,
  167. <<<'PHP'
  168. <?php
  169. class FooTest extends \PHPUnit\Framework\TestCase {
  170. /**
  171. * @copyright ACME Corporation
  172. * @dataProvider provideFooCases
  173. * @requires PHP ^8.2
  174. * @requires OS Linux|Darwin
  175. */
  176. public function testFoo($x) { self::assertTrue($x); }
  177. public static function provideFooCases() { yield [true]; yield [false]; }
  178. }
  179. PHP,
  180. ];
  181. yield 'fix with multiple spaces' => [
  182. <<<'PHP'
  183. <?php
  184. class FooTest extends \PHPUnit\Framework\TestCase {
  185. /**
  186. */
  187. #[\PHPUnit\Framework\Attributes\RequiresPhp('^7.4|^8.1')]
  188. public function testFoo() { self::assertTrue(true); }
  189. }
  190. PHP,
  191. <<<'PHP'
  192. <?php
  193. class FooTest extends \PHPUnit\Framework\TestCase {
  194. /**
  195. * @requires PHP ^7.4|^8.1
  196. */
  197. public function testFoo() { self::assertTrue(true); }
  198. }
  199. PHP,
  200. ];
  201. yield 'fix with > in operator' => [
  202. <<<'PHP'
  203. <?php
  204. class FooTest extends \PHPUnit\Framework\TestCase {
  205. /**
  206. */
  207. #[\PHPUnit\Framework\Attributes\RequiresPhp('>= 8.1')]
  208. public function testFoo() { self::assertTrue(true); }
  209. }
  210. PHP,
  211. <<<'PHP'
  212. <?php
  213. class FooTest extends \PHPUnit\Framework\TestCase {
  214. /**
  215. * @requires PHP >= 8.1
  216. */
  217. public function testFoo() { self::assertTrue(true); }
  218. }
  219. PHP,
  220. ];
  221. yield 'fix with trailing spaces' => self::createCase(
  222. ['class'],
  223. '#[CoversClass(Foo::class)]',
  224. '@covers Foo ',
  225. );
  226. $byte224 = \chr(224);
  227. yield 'fix with non-alphanumeric characters' => [
  228. <<<PHP
  229. <?php
  230. class FooTest extends \\PHPUnit\\Framework\\TestCase {
  231. /**
  232. */
  233. #[\\PHPUnit\\Framework\\Attributes\\TestDox('a\\'b"c')]
  234. public function testFoo() { self::assertTrue(true); }
  235. /**
  236. */
  237. #[\\PHPUnit\\Framework\\Attributes\\TestDox('龍')]
  238. public function testBar() { self::assertTrue(true); }
  239. /**
  240. */
  241. #[\\PHPUnit\\Framework\\Attributes\\TestDox('byte224: {$byte224}')]
  242. public function testBaz() { self::assertTrue(true); }
  243. }
  244. PHP,
  245. <<<PHP
  246. <?php
  247. class FooTest extends \\PHPUnit\\Framework\\TestCase {
  248. /**
  249. * @testDox a'b"c
  250. */
  251. public function testFoo() { self::assertTrue(true); }
  252. /**
  253. * @testDox 龍
  254. */
  255. public function testBar() { self::assertTrue(true); }
  256. /**
  257. * @testDox byte224: {$byte224}
  258. */
  259. public function testBaz() { self::assertTrue(true); }
  260. }
  261. PHP,
  262. ];
  263. yield 'handle After' => self::createCase(
  264. ['method'],
  265. '#[After]',
  266. '@after',
  267. );
  268. yield 'handle AfterClass' => self::createCase(
  269. ['method'],
  270. '#[AfterClass]',
  271. '@afterClass',
  272. );
  273. yield 'handle BackupGlobals enabled' => self::createCase(
  274. ['class', 'method'],
  275. '#[BackupGlobals(true)]',
  276. '@backupGlobals enabled',
  277. );
  278. yield 'handle BackupGlobals disabled' => self::createCase(
  279. ['class', 'method'],
  280. '#[BackupGlobals(false)]',
  281. '@backupGlobals disabled',
  282. );
  283. yield 'handle BackupGlobals no' => self::createCase(
  284. ['class', 'method'],
  285. '#[BackupGlobals(false)]',
  286. '@backupGlobals no',
  287. );
  288. yield 'handle BackupStaticProperties enabled' => self::createCase(
  289. ['class', 'method'],
  290. '#[BackupStaticProperties(true)]',
  291. '@backupStaticAttributes enabled',
  292. );
  293. yield 'handle BackupStaticProperties disabled' => self::createCase(
  294. ['class', 'method'],
  295. '#[BackupStaticProperties(false)]',
  296. '@backupStaticAttributes disabled',
  297. );
  298. yield 'handle Before' => self::createCase(
  299. ['method'],
  300. '#[Before]',
  301. '@before',
  302. );
  303. yield 'handle BeforeClass' => self::createCase(
  304. ['method'],
  305. '#[BeforeClass]',
  306. '@beforeClass',
  307. );
  308. yield 'handle CoversClass' => self::createCase(
  309. ['class'],
  310. '#[CoversClass(\VendorName\ClassName::class)]',
  311. '@covers \VendorName\ClassName',
  312. );
  313. yield 'handle CoversFunction' => self::createCase(
  314. ['class'],
  315. "#[CoversFunction('functionName')]",
  316. '@covers ::functionName',
  317. );
  318. yield 'handle CoversNothing' => self::createCase(
  319. ['class', 'method'],
  320. '#[CoversNothing]',
  321. '@coversNothing',
  322. );
  323. yield 'handle DataProvider' => self::createCase(
  324. ['method'],
  325. "#[DataProvider('provideFooCases')]",
  326. '@dataProvider provideFooCases',
  327. );
  328. yield 'handle DataProviderExternal' => self::createCase(
  329. ['method'],
  330. "#[DataProviderExternal(BarTest::class, 'provideFooCases')]",
  331. '@dataProvider BarTest::provideFooCases',
  332. );
  333. yield 'handle Depends' => self::createCase(
  334. ['method'],
  335. "#[Depends('methodName')]",
  336. '@depends methodName',
  337. );
  338. yield 'handle DependsExternal' => self::createCase(
  339. ['method'],
  340. "#[DependsExternal(ClassName::class, 'methodName')]",
  341. '@depends ClassName::methodName',
  342. );
  343. yield 'handle DependsExternalUsingDeepClone' => self::createCase(
  344. ['method'],
  345. "#[DependsExternalUsingDeepClone(ClassName::class, 'methodName')]",
  346. '@depends clone ClassName::methodName',
  347. );
  348. yield 'handle DependsExternalUsingShallowClone' => self::createCase(
  349. ['method'],
  350. "#[DependsExternalUsingShallowClone(ClassName::class, 'methodName')]",
  351. '@depends shallowClone ClassName::methodName',
  352. );
  353. yield 'handle DependsOnClass' => self::createCase(
  354. ['method'],
  355. '#[DependsOnClass(ClassName::class)]',
  356. '@depends ClassName::class',
  357. );
  358. yield 'handle DependsOnClassUsingDeepClone' => self::createCase(
  359. ['method'],
  360. '#[DependsOnClassUsingDeepClone(ClassName::class)]',
  361. '@depends clone ClassName::class',
  362. );
  363. yield 'handle DependsOnClassUsingShallowClone' => self::createCase(
  364. ['method'],
  365. '#[DependsOnClassUsingShallowClone(ClassName::class)]',
  366. '@depends shallowClone ClassName::class',
  367. );
  368. yield 'handle DependsUsingDeepClone' => self::createCase(
  369. ['method'],
  370. "#[DependsUsingDeepClone('methodName')]",
  371. '@depends clone methodName',
  372. );
  373. yield 'handle DependsUsingShallowClone' => self::createCase(
  374. ['method'],
  375. "#[DependsUsingShallowClone('methodName')]",
  376. '@depends shallowClone methodName',
  377. );
  378. yield 'handle DoesNotPerformAssertions' => self::createCase(
  379. ['class', 'method'],
  380. '#[DoesNotPerformAssertions]',
  381. '@doesNotPerformAssertions',
  382. );
  383. yield 'handle Group' => self::createCase(
  384. ['class', 'method'],
  385. "#[Group('groupName')]",
  386. '@group groupName',
  387. );
  388. yield 'handle Large' => self::createCase(
  389. ['class'],
  390. '#[Large]',
  391. '@large',
  392. );
  393. yield 'handle Medium' => self::createCase(
  394. ['class'],
  395. '#[Medium]',
  396. '@medium',
  397. );
  398. yield 'handle PostCondition' => self::createCase(
  399. ['method'],
  400. '#[PostCondition]',
  401. '@postCondition',
  402. );
  403. yield 'handle PreCondition' => self::createCase(
  404. ['method'],
  405. '#[PreCondition]',
  406. '@preCondition',
  407. );
  408. yield 'handle PreserveGlobalState enabled' => self::createCase(
  409. ['class', 'method'],
  410. '#[PreserveGlobalState(true)]',
  411. '@preserveGlobalState enabled',
  412. );
  413. yield 'handle PreserveGlobalState disabled' => self::createCase(
  414. ['class', 'method'],
  415. '#[PreserveGlobalState(false)]',
  416. '@preserveGlobalState disabled',
  417. );
  418. yield 'handle RequiresFunction' => self::createCase(
  419. ['class', 'method'],
  420. "#[RequiresFunction('imap_open')]",
  421. '@requires function imap_open',
  422. );
  423. yield 'handle RequiresMethod' => self::createCase(
  424. ['class', 'method'],
  425. "#[RequiresMethod(ReflectionMethod::class, 'setAccessible')]",
  426. '@requires function ReflectionMethod::setAccessible',
  427. );
  428. yield 'handle RequiresOperatingSystem' => self::createCase(
  429. ['class', 'method'],
  430. "#[RequiresOperatingSystem('Linux')]",
  431. '@requires OS Linux',
  432. );
  433. yield 'handle RequiresOperatingSystemFamily' => self::createCase(
  434. ['class', 'method'],
  435. "#[RequiresOperatingSystemFamily('Windows')]",
  436. '@requires OSFAMILY Windows',
  437. );
  438. yield 'handle RequiresPhp' => self::createCase(
  439. ['class', 'method'],
  440. "#[RequiresPhp('8.1.20')]",
  441. '@requires PHP 8.1.20',
  442. );
  443. yield 'handle RequiresPhpExtension' => self::createCase(
  444. ['class', 'method'],
  445. "#[RequiresPhpExtension('mysqli', '>= 8.3.0')]",
  446. '@requires extension mysqli >= 8.3.0',
  447. );
  448. yield 'handle RequiresPhpunit' => self::createCase(
  449. ['class', 'method'],
  450. "#[RequiresPhpunit('^10.1.0')]",
  451. '@requires PHPUnit ^10.1.0',
  452. );
  453. yield 'handle RequiresSetting' => self::createCase(
  454. ['class', 'method'],
  455. "#[RequiresSetting('date.timezone', 'Europe/London')]",
  456. '@requires setting date.timezone Europe/London',
  457. );
  458. yield 'handle RunInSeparateProcess' => self::createCase(
  459. ['method'],
  460. '#[RunInSeparateProcess]',
  461. '@runInSeparateProcess',
  462. );
  463. yield 'handle RunTestsInSeparateProcesses' => self::createCase(
  464. ['class'],
  465. '#[RunTestsInSeparateProcesses]',
  466. '@runTestsInSeparateProcesses',
  467. );
  468. yield 'handle Small' => self::createCase(
  469. ['class'],
  470. '#[Small]',
  471. '@small',
  472. );
  473. yield 'handle Test' => self::createCase(
  474. ['method'],
  475. '#[Test]',
  476. '@test',
  477. );
  478. yield 'handle TestDox' => self::createCase(
  479. ['class', 'method'],
  480. "#[TestDox('Hello world!')]",
  481. '@testDox Hello world!',
  482. );
  483. yield 'handle Ticket' => self::createCase(
  484. ['class', 'method'],
  485. "#[Ticket('ABC-123')]",
  486. '@ticket ABC-123',
  487. );
  488. yield 'handle UsesClass' => self::createCase(
  489. ['class'],
  490. '#[UsesClass(ClassName::class)]',
  491. '@uses ClassName',
  492. );
  493. yield 'handle UsesFunction' => self::createCase(
  494. ['class'],
  495. "#[UsesFunction('functionName')]",
  496. '@uses ::functionName',
  497. );
  498. yield 'handle TestWith' => [
  499. <<<'PHP'
  500. <?php
  501. /**
  502. * @testWith [true, false]
  503. */
  504. class FooTest extends \PHPUnit\Framework\TestCase {
  505. /**
  506. */
  507. #[\PHPUnit\Framework\Attributes\TestWithJson('[1, 2]')]
  508. public function testFoo($x) {}
  509. /**
  510. */
  511. #[\PHPUnit\Framework\Attributes\TestWithJson('[3, 4, 5]')]
  512. #[\PHPUnit\Framework\Attributes\TestWithJson('[6, 7, 8]')]
  513. #[\PHPUnit\Framework\Attributes\TestWithJson('["a", "b"]')]
  514. #[\PHPUnit\Framework\Attributes\TestWithJson('["c\'d"]')]
  515. public function testBar($x) {}
  516. }
  517. PHP,
  518. <<<'PHP'
  519. <?php
  520. /**
  521. * @testWith [true, false]
  522. */
  523. class FooTest extends \PHPUnit\Framework\TestCase {
  524. /**
  525. * @testWith [1, 2]
  526. */
  527. public function testFoo($x) {}
  528. /**
  529. * @testWith [3, 4, 5]
  530. * [6, 7, 8]
  531. * ["a", "b"]
  532. * ["c'd"]
  533. */
  534. public function testBar($x) {}
  535. }
  536. PHP,
  537. ];
  538. yield 'handle multiple annotations of the same name' => [
  539. <<<'PHP'
  540. <?php
  541. /**
  542. */
  543. #[\PHPUnit\Framework\Attributes\Group('foo')]
  544. #[\PHPUnit\Framework\Attributes\Group('bar')]
  545. class TheTest extends \PHPUnit\Framework\TestCase {}
  546. PHP,
  547. <<<'PHP'
  548. <?php
  549. /**
  550. * @group foo
  551. * @group bar
  552. */
  553. class TheTest extends \PHPUnit\Framework\TestCase {}
  554. PHP,
  555. ];
  556. yield 'keep annotations' => [
  557. <<<'PHP'
  558. <?php
  559. class FooTest extends \PHPUnit\Framework\TestCase {
  560. /**
  561. * @copyright ACME Corporation
  562. * @dataProvider provideFooCases
  563. * @requires PHP ^8.2
  564. * @requires OS Linux|Darwin
  565. */
  566. #[\PHPUnit\Framework\Attributes\DataProvider('provideFooCases')]
  567. #[\PHPUnit\Framework\Attributes\RequiresPhp('^8.2')]
  568. #[\PHPUnit\Framework\Attributes\RequiresOperatingSystem('Linux|Darwin')]
  569. public function testFoo($x) { self::assertTrue($x); }
  570. public static function provideFooCases() { yield [true]; yield [false]; }
  571. }
  572. PHP,
  573. <<<'PHP'
  574. <?php
  575. class FooTest extends \PHPUnit\Framework\TestCase {
  576. /**
  577. * @copyright ACME Corporation
  578. * @dataProvider provideFooCases
  579. * @requires PHP ^8.2
  580. * @requires OS Linux|Darwin
  581. */
  582. public function testFoo($x) { self::assertTrue($x); }
  583. public static function provideFooCases() { yield [true]; yield [false]; }
  584. }
  585. PHP,
  586. [
  587. 'keep_annotations' => true,
  588. ],
  589. ];
  590. }
  591. /**
  592. * @param non-empty-list<'class'|'method'> $scopes
  593. *
  594. * @return array{string, string}
  595. */
  596. private static function createCase(array $scopes, string $expectedAttribute, string $inputAnnotation): array
  597. {
  598. $expectedAttribute = str_replace('#[', '#[\PHPUnit\Framework\Attributes\\', $expectedAttribute);
  599. return [
  600. \sprintf(
  601. <<<'PHP'
  602. <?php
  603. %s
  604. class FooTest extends \PHPUnit\Framework\TestCase {
  605. %s
  606. public function testFoo($x) {}
  607. %s
  608. public function testBar($x) {}
  609. }
  610. PHP,
  611. \in_array('class', $scopes, true)
  612. ? \sprintf("/**\n */\n%s", $expectedAttribute)
  613. : \sprintf("/**\n * %s\n */", $inputAnnotation),
  614. \in_array('method', $scopes, true)
  615. ? \sprintf("/**\n */\n %s", $expectedAttribute)
  616. : \sprintf("/**\n * %s\n */", $inputAnnotation),
  617. \in_array('method', $scopes, true)
  618. ? \sprintf("\n %s", $expectedAttribute)
  619. : \sprintf('/** %s */', $inputAnnotation),
  620. ),
  621. \sprintf(
  622. <<<'PHP'
  623. <?php
  624. /**
  625. * %s
  626. */
  627. class FooTest extends \PHPUnit\Framework\TestCase {
  628. /**
  629. * %s
  630. */
  631. public function testFoo($x) {}
  632. /** %s */
  633. public function testBar($x) {}
  634. }
  635. PHP,
  636. $inputAnnotation,
  637. $inputAnnotation,
  638. $inputAnnotation,
  639. ),
  640. ];
  641. }
  642. }