giorgiosironi/eris

Annotations

Closed this issue · 5 comments

Hi there! Fantastic work.

I just recently learned about property testing using hypothesis (Python). I've found really cool that you can use decorators in Python.

Do you think it would be possible to do something similar with annotations? Similar to how @dataProvider works?

AFAIK PHPUnit does not have support for plugging in test discoverability or custom annotations. However, nothing would stop a @dataProvider annotation that points to a method with some syntactic sugar from working. I have doubts on whether shrinking would be possible.

There is two issues with trying to use data providers with PHPUnit:

  • The @dataProvider annotation does not support functions
  • You could get around the first point with @dataProvider \Eris\Generator\BooleanGenerator::__invoke, the remaining issue is that you are going to yield values where PHPUnit expects an array of arguments

As a result what you would need is:

class AcmeTest extends TestCase {
    function provideBoolean(): \Generator
    {
        yield [\Eris\Generator\bool()];
    }
}

So maybe the simplest way to go would be to provide in the trait Eris\TestTrait (which IMO should be renamed Eris\PhpUnitProvider provider functions like the one I gave above.

This is a must as without it, well I don't find the native syntax as readable as I would like it to be, but more importantly otherwise Eris is hardly usable as you may need the setUp() and tearDown() methods to be called between each values provided.

Thoughts?

How could this be extended to allow multiple parameters to be passed in (e.g. a pair of a boolean and an integer), or any kind of testing structure? Some sort of __call() magic?

I think some support for more dynamic data providers would be needed on the PHPUnit side, if an object could be used it would simplify the picture.

I'm not sure to be honest. Maybe having a data provider for an argument as opposed to a data provider that must provide all the arguments would help as the later makes it very hard to re-use the existing data providers...

anything related to yield is currently impossible with sebastianbergmann/phpunit#10 - data is fully collected before running tests, removing any chance of generators being used (see sebastianbergmann/phpunit#2034 (comment)).

Annotations that could already work without issues would be the configurations, for example:

    /**
     * @before
     */
    public function erisSetup()
    {
        $this->seedingRandomNumberGeneration();
        $tags = $this->getAnnotations();//from TestCase of PHPunit
        $this->withRand($this->getAnnotationValue($tags, 'eris-method', 'rand'));
        $this->limitTo((int) $this->getAnnotationValue($tags, 'eris-repeat', 100));
        $this->shrinkingTimeLimit($this->getAnnotationValue($tags, 'eris-shrink', null));
        $this->minimumEvaluationRatio($this->getAnnotationValue($tags, 'eris-ratio', 50)/100);
    }

    /**
     * @param array $annotations
     * @param string $key
     * @param mixed $default
     * @return mixed
     */
    private function getAnnotationValue(array $annotations, $key, $default)
    {
        $annotation = $this->getAnnotation($annotations, $key);
        return isset($annotation[0])?$annotation[0]:$default;
    }

    /**
     * @param array $annotations
     * @param string $key
     * @return array
     */
    private function getAnnotation(array $annotations, $key)
    {
        if (isset($annotations['method'][$key])) {
            return $annotations['method'][$key];
        }
        return isset($annotations['class'][$key])?$annotations['class'][$key]:[];
    }

That would allow for most of the protected methods to be removed to be honest. If there's interest I can clean up the trait tonight and add annotations.