xp-framework / unittest

Unittests for the XP Framework
0 stars 0 forks source link

PHP 8 attributes #40

Closed thekid closed 1 year ago

thekid commented 4 years ago

With the introduction of attributes in PHP 8, XP annotations can be changed over to PHP attributes. Aiding this transition will be the introduction of a new library for reflection (see xp-framework/rfc#336), which will work with both PHP 7 and PHP 8 (given that we don't use multiline attributes nor attributes on the same line as the values they're decoration, both of which will cause parsing errors). However, the new syntax also offers a couple of possibilities we can take advantage of.

XP annotation PHP attribute Comment
#[@test] #[Test]
#[@before] #[Before] Baseless tests
#[@after] #[After] Baseless tests
#[@beforeClass] #[BeforeClass] TestCase descendants
#[@afterClass] #[AfterClass] TestCase descendants
#[@ignore('Reason')] #[Ignore('Reason')]
#[@expect(Throwable::class)] #[Expect(Throwable::class)]
#[@expect(['class' => E::class])] #[Expect(class: E::class)] Changed to named argument
#[@limit(['time' => 1)] #[Limit(time: 1)] Changed to named argument
#[@values('provider')] #[Values('provider')]]
#[@values([1, 2, 3])] #[Values([1, 2, 3])]]
#[@values([self::$TYPE])] #[Values(eval: '[self::$TYPE]')]] Workaround for missing PHP support
#[@action(new Version('>=7.0'))] #[Version('>=7.0')] Actions become standalone
thekid commented 4 years ago

Note: fn expressions inside eval arguments will be rewritten to function() { ... } in order to work with all PHP 7 versions.

thekid commented 4 years ago
diff --git a/src/main/php/unittest/TestGroup.class.php b/src/main/php/unittest/TestGroup.class.php
index 8606b05..d528771 100755
--- a/src/main/php/unittest/TestGroup.class.php
+++ b/src/main/php/unittest/TestGroup.class.php
@@ -18,15 +18,24 @@ abstract class TestGroup {
    * @return iterable
    */
   protected function actionsFor($annotated, $kind) {
-    if (null === ($annotation= $annotated->annotation('action'))) return;

-    $action= $annotation->argument(0);
-    if (is_array($action)) {
-      foreach ($action as $a) {
-        if ($a instanceof $kind) yield $a;
+    // XP: [@action(new RuntimeVersion(...))]
+    if ($annotation= $annotated->annotation(Action::class)) {
+      $action= $annotation->argument(0);
+      if (is_array($action)) {
+        foreach ($action as $a) {
+          if ($a instanceof $kind) yield $a;
+        }
+      } else {
+        if ($action instanceof $kind) yield $action;
+      }
+    }
+
+    // PHP: [RuntimeVersion(<const>), VerifyThat(eval: '<expr>')]
+    foreach ($annotated->annotations() as $type => $annotation) {
+      if ($annotation->is($kind)) {
+        yield Reflect::of($type)->newInstance(...$annotation->arguments());
       }
-    } else {
-      if ($action instanceof $kind) yield $action;
     }
   }
thekid commented 1 year ago

Will be fully implemented in https://github.com/xp-framework/test