xp-framework / unittest

Unittests for the XP Framework
0 stars 0 forks source link

Command line plugins #32

Closed thekid closed 1 year ago

thekid commented 6 years ago

The new coverage library adds code coverage functionality to the unittest library. However, it requires the user to type this complicated command line:

$ xp test -l unittest.coverage.CoverageListener - -o registerpath src/main/php src/test/php
#         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#         This is necessary to instantiate and configure the coverage library!

This is due to the generic way of handling listener implementations.


It would be great if the command was easier, e.g. something like:

$ xp test --coverage=src/main/php src/test/php
#         ^^^^^^^^^^^^^^^^^^^^^^^

An external library would need to be able to integrate itself with the command line parsing routine somehow to achieve this.

/cc @OlafSeng

thekid commented 6 years ago

...and that would also give us a change to simplify all of the following code which handles the -l and -o command line options:

} else if ('-l' == $args[$i]) {
  $arg= $this->arg($args, ++$i, 'l');
  $class= XPClass::forName(strstr($arg, '.') ? $arg : 'xp.unittest.'.ucfirst($arg).'Listener');
  $arg= $this->arg($args, ++$i, 'l');
  if ('-?' == $arg || '--help' == $arg) {
    return $this->listenerUsage($class);
  }
  $output= $this->streamWriter($arg);
  $instance= $suite->addListener($class->newInstance($output));

  // Get all @arg-annotated methods
  $options= [];
  foreach ($class->getMethods() as $method) {
    if ($method->hasAnnotation('arg')) {
      $arg= $method->getAnnotation('arg');
      if (isset($arg['position'])) {
        $options[$arg['position']]= $method;
      } else {
        $name= isset($arg['name']) ? $arg['name'] : strtolower(preg_replace('/^set/', '', $method->getName()));
        $short= isset($arg['short']) ? $arg['short'] : $name{0};
        $options[$name]= $options[$short]= $method;
      }
    }
  }
  $option= 0;
} else if ('-o' == $args[$i]) {
  if (isset($options[$option])) {
    $name= '#'.($option+ 1);
    $method= $options[$option];
  } else {
    $name= $this->arg($args, ++$i, 'o');
    if (!isset($options[$name])) {
      $this->err->writeLine('*** Unknown listener argument '.$name.' to '.nameof($instance));
      return 2;
    }
    $method= $options[$name];
  }
  $option++;
  if (0 == $method->numParameters()) {
    $pass= [];
  } else {
    $pass= $this->arg($args, ++$i, 'o '.$name);
  }
  try {
    $method->invoke($instance, $pass);
  } catch (TargetInvocationException $e) {
    $this->err->writeLine('*** Error for argument '.$name.' to '.nameof($instance).': '.$e->getCause()->toString());
    return 2;
  }
}

See src/main/php/xp/unittest/TestRunner.class.php

thekid commented 6 years ago

One easy idea is to create a subcommand which invokes xp.unittest.TestRunner, see xp-forge/coverage#1

thekid commented 1 year ago

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