sebastianbergmann / phpunit

The PHP Unit Testing framework.
https://phpunit.de/
BSD 3-Clause "New" or "Revised" License
19.7k stars 2.2k forks source link

@testWith feature #1151

Closed farafiri closed 9 years ago

farafiri commented 10 years ago

It would be great to have @testWith (like JUnit) feature:

/**
 * @testWith (1, 2, 3)
 *           (10, 11, 21)
 */
function testAdd($a, $b, $result)
{
  $this->assertEquals($result, $sut->add($a, $b));
}

I know that I can use @dataProvider but it overcomplicated and require to much code for most tasks.

drgomesp commented 10 years ago

@farafiri, can you please explain what exactly is the difference between the @dataProvider annotation feature and what you just described – besides the fact that you don't define a real method that actually provides the data?

farafiri commented 10 years ago

None. It's only syntactic sugar. Easer to write and read. Jumping around methods to find out what cases are tested is disturbing.

drgomesp commented 10 years ago

@farafiri I guess one of the bright sides of having provider methods is that you can reuse them – not sure if that's a good practice, though.

farafiri commented 10 years ago

You are right, but in most cases you don't need reusability, in most cases you need readability.

In case when programmer realise that he made bad choice using @testWith because he needs reusability/mock as parameter/whatever switching into @dataProvier is very easy and safe operation.

whatthejeff commented 10 years ago

@sebastianbergmann thoughts? I kind of like it.

sebastianbergmann commented 10 years ago

+1 from me :) Just make sure that internally the data provider infrastructure is reused.

giorgiosironi commented 9 years ago

@farafiri do you mind if I build on bf1c416 and open a PR with a complete implementation?

farafiri commented 9 years ago

It would be great. Thank you.

marcinrogacki commented 9 years ago

Hello,

I came here to propose such feature. That nice it is already done.

A few thoughts (according to: https://github.com/sebastianbergmann/phpunit/pull/1728). @sebastianbergmann @giorgiosironi Please express your opinions about them.

1) Why do not use old good @dataProvider annotation instead of adding new one @testWith? In my opinion distinguish between function and data set shouldn't be complicated.

2) Simplify syntax (more space for large data list, faster to write, easier to read)

@dataProvider
0, 1, 1
1, 2, 3
20, 22, 42

3) Support complex types (inspared by https://code.google.com/p/zohhak/). Requirements: parse test method signature to find complex types, parse class file to find desired function which will create complex type. Search could support @return phpdoc.

Example 1

    /**
     * @dataProvider
     *  "EUR", "FR", 
     *  "GBP", "UK"
     *  "USD", "US"
     */
    public function testCountryUsesCurrency(Currency $currency, Country $country)
    {
        $this->assertTrue($country->isDefaultCurrency($currency));
    }

   /**
    * @return Currency
    */
   public function createCurrency($currency)
   {
       return new Currency($currency);
   }

   /**
    * @return Country
    */
   public function createCountry($country)
   {
       return new Country($country);
   }

Example 2

    /**
     * @dataProvider
     *  [49.95, "EUR"], "ACCEPTED",  49.95, "EUR"
     *  [39.95, "GBP"], "REFUSED", 0, "GBP"
     */
    public function testCapturePayment(
        Namespace_Order $order, Zend_Soap_Client $gateway,
       $expectedAmount, $expectedCurrency
    ) {
        $payment = new Payment($gateway, $order);
        $transaction = $payment->capture();
        $this->assertEquals($expectedAmount, $transaction->getAmount());
        $this->assertEquals($expectedCurrency, $transaction->getCurrency());
    }

   /**
    * @return Zend_Soap_Client
    */
   public function createStubPaymentGateway($status)
   {
        $stub = $this->getMockBuilder('Zend_Soap_Client')->getMock();
        $stub->method('getResult')->willReturn($status);
        return $stub;
   }

   /**
    * @return Namespace_Order
    */
   public function createOrder($amount, $currency)
   {
       return new Namespace_Order($amount, $country);
   }
marcinrogacki commented 9 years ago

@sebastianbergmann @giorgiosironi @whatthejeff bump

sebastianbergmann commented 9 years ago

1) Separation of concerns

2) I don't see the point

3) Too much work (not to implement it but at runtime)