pestphp / pest

Pest is an elegant PHP testing Framework with a focus on simplicity, meticulously designed to bring back the joy of testing in PHP.
https://pestphp.com
MIT License
9.42k stars 338 forks source link

Troubleshooting: What pain points did you encounter while trying Pest? #33

Closed alexmartinfr closed 3 years ago

alexmartinfr commented 4 years ago

In an effort to improve Pest and its documentation, we would like to collect your experience trying Pest for the first time. Remember, there is no wrong answer 🙂

To get the ball rolling, I'll share my first roadblock:

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use App\User;

uses(
    RefreshDatabase::class,
    TestCase::class,
    User::class,
)->in('Feature');

Your turn now! What troubles did you experience using Pest?

dmason30 commented 4 years ago

I would like to preface the below in saying I have really enjoyed using this since launch and it does make a great number of things easier and results in cleaner tests (in most cases) so many thanks to all the contributors its a great package.

I have been using PHPUnit/Laravel for around 7 years and I am very fluent of it at this stage. I don't know every assertion method off by heart as generally there is only a dozen I use on a regular basis.

I am creating a rather complex package to generate pest tests as an addon to Laravel Shift's Blueprint here is a link to the only tests I intend to write for it and use the with() to handle the required scenarios https://github.com/fidum/laravel-blueprint-pestphp-addon/blob/master/tests/Feature/PestGeneratorTest.php.

1. Handling private methods I traditionally used private/protected methods in my test classes where code is shared between tests or even just to make a test more concise and readable. The roadblock here was deciding where to they belong?

I decided at the moment to put them in the parent test case - not sure if the docs should recommend an approach for this?

2. Code completion I love me some code completion and I expected that this would be an issue when moving from classes to closures.

So when using $this without any kind of hinting you will not get code completion and for some they don't need it which is great!

I ended up using the @var to type hint this for me.

/** @var FeatureTestCase $this` */

But I understand that to a lot of people this is a bit over the top. So because of this I will probably endup putting any traits in the parent TestCase if I have created one for further completion rather than using the uses(TestCase::class, //...traits).

nunomaduro commented 4 years ago
  1. Handling private methods

Get this question all the time. I think this deserve a guide.

dsampaolo commented 4 years ago

Hello,

First timer with Pest, I know how to use phpUnit and write tests with it. I use it mainly with Laravel.

I like to unit-tests my API routes (for example, to check that "api:auth" middleware is enforced on all restricted routes). I didn't (ye) find a simple way to add an "Accept: application/json" header to my test :

it('needs to be logged in')->get('/api/user')->assertStatus(401);

Anyway, thanks for your great work! :)

fetzi commented 4 years ago

Hey @dsampaolo, you can do this by adding a second parameter to the get method:

it('needs to be logged in')->get('/api/user', ['Accept' => 'application/json'])->assertStatus(401);
dsampaolo commented 4 years ago

Hi @fetzi,

Thanks a lot. I just realized that I can use getJson() as well :

it('needs to be logged in')->getJson('/api/user')->assertStatus(401);

Thank you again ! :)

alexmartinfr commented 4 years ago

This one is closed, but I'll link this one for future reference: #38

Interesting confusion I think. Laravel used to have a visit() method for testing which is now replaced by get().

Even if not directly Pest-related, it could deserve a spot in a Troubleshooting/common issues section. People would then find it via keyword research. SEO but for documentation 👌

erikaheidi commented 4 years ago

Hello :wave:

Starting with my background in tests: I'm a test newbie, I have written tests before just "following along" within an existing project and also had experience writing tests in Ruby, and that was a lot easier than testing with PHPUnit. The first time I actually bootstrapped a testing env for a project was with Pest, and my project is fairly simple - it's CLI-based, so there's no front-end.

As someone with little experience, I was able to pick up things quite quickly, but I got stuck a bit with how to test the output of my CLI scripts. I figured out how to do that with expectOutputString while searching more broadly for PHPUnit assertions and stuff.

One thing that didn't work thou, was using a function set in the Helpers inside the expectOutputString - I think it's out of scope? I created a helper function to format the output more easily so that I could test my cli printing stuff, but I was only able to use a function inside expectOutputString if it was defined in the test file itself. Maybe I'm doing something wrong, thou, so please let me know :)

Anyways, I'm very happy with Pest :)

nunomaduro commented 4 years ago

As someone with little experience, I was able to pick up things quite quickly, but I got stuck a bit with how to test the output of my CLI scripts. I figured out how to do that with expectOutputString while searching more broadly for PHPUnit assertions and stuff.

I think we can add more assertions to Pest docs.

One thing that didn't work thou, was using a function set in the Helpers inside the expectOutputString - I think it's out of scope? I created a helper function to format the output more easily so that I could test my cli printing stuff, but I was only able to use a function inside expectOutputString if it was defined in the test file itself. Maybe I'm doing something wrong, thou, so please let me know :)

Can I see some code @erikaheidi ?

Thanks!

romainnorberg commented 4 years ago

Hi @AlexMartinFR, I'm migrating my tests to PEST. It seems to me that @nunomaduro talked about an existing integration with spatie/phpunit-snapshot-assertions but I can't find where. I did a test but the snapshot is located in vendor/pestphp/pest/src/Factories/__ snapshots__/* instead of being in the directory of the test file (the latter is the default behavior of spatie package)

Screenshot 2020-05-30 at 21 55 27

Thanks in advance

owenvoke commented 4 years ago

@romainnorberg, snapshots should be stored in the same place. 👍 Nuno may have been referring to the snapshots wrapper for Pest. https://github.com/spatie/pest-plugin-snapshots

nunomaduro commented 4 years ago

@owenvoke @romainnorberg its under works. Just waiting for @freekmurze to validate a pull request in progress.

romainnorberg commented 4 years ago

Thanks @owenvoke @nunomaduro ✌️

alexmartinfr commented 4 years ago

Lots of good leads on how to improve the experience of new users 💯

It'll take some time to process everything and come up with solutions, but I wanted to let everyone know how much we appreciate you taking the time to answer ❤️

Keep these coming!

nobuf commented 4 years ago

I like Datasets compared to @dataProvider and fresh colorful looking :)

Not really a pain point but I found a couple of surprises:

bash 2020-06-07 18-35-22

Thanks!

alexmartinfr commented 4 years ago

Thanks @nobuf for bringing up this accessibility hiccup! 👍 Please check this Collision issue and feel free to chime in if you have more to add: https://github.com/nunomaduro/collision/issues/123

Regarding the output printing, could you open an issue about that, with more details about your use-case?

fbraem commented 4 years ago

I assumed that I could initialize some context variables (a database connection for example) in a beforeAll closure and use that context in a skip. But it turns out that skip is called before beforeAll.

So this:

$context = new stdClass();

beforeAll(function () use ($context) {
    try {
        $context->db = withDatabase();
    } catch (DatabaseException $e) {
    }
});

it('can find a record a given id', function () use ($context) {
   $repo = new ClientRepo(context->db);
   ...
})
    ->skip(!isset($context->db), 'No database available')
;

doesn't work because $context->db is not yet available.

nunomaduro commented 4 years ago

Why you don't use beforeEach?

fbraem commented 4 years ago

My intention was to ignore the tests when there is no connection to a database. If I set the database in beforeEach, the tests will still be executed when there is no connection. Or am I missing something?

I also noticed that Helpers (withDatabase function is located there) are available in Pest.php. Calling withDatabase in Pest.php for the first time, will make it possible to check the database connection in skip.

avrahamappel commented 4 years ago

Hi! I'm enjoying the clean syntax of this package a lot. Here's one thing that confused me when using datasets. I sometimes use initialized objects in datasets and it's difficult to tell which dataset is used when you see

  ✓ it passes the test with (App\User Object(...), App\Post Object(...))
  ✓ it passes the test with (App\User Object(...), App\Post Object(...))

I tried adding string keys to the dataset array, but Pest doesn't seem to use them for labels as PHPUnit does, I still see the full array in the output.

dataset('my-dataset', [
    'first dataset' => [new User(['name' => 'John Doe']), new Post()],
    'second dataset' => [new User(['name' => 'Jane Doe']), new Post()],
]);

Is there a way to add labels to the datasets?

hackel commented 4 years ago

I just discovered that it's not possible to run Pest and PHPUnit side-by-side, as PHPUnit will try to run my Pest test files, which then throw an InvalidPestCommand exception before any tests have run. Of course I would like to eventually get everything over to Pest, but this is going to take time, so a progressive migration would be preferred.

It seems like for now I'm just going to have to put my Pest tests in a separate directory and pass a separate pest.xml file on the command line that point to them. I could see this being a potential pain point for other new users.

owenvoke commented 4 years ago

@hackel, Pest should run all your PHPUnit tests as well due to it being a progressive framework. 🤔

hackel commented 4 years ago

@owenvoke Yes, Pest runs my PHPUnit tests beautifully, but PHPUnit can no longer run its own tests. Eventually I'll get around to integrating Pest into our custom CI, but until then we still need to run PHPUnit.

As an interim solution, I've just added this to the top of all my Pest tests.

try {
    \Pest\TestSuite::getInstance();
} catch (\Pest\Exceptions\InvalidPestCommand $e) {
    return;
}
owenvoke commented 4 years ago

Oh right, I see. 👍🏻

nunomaduro commented 3 years ago

Any progress on this issue?

nunomaduro commented 3 years ago

I'm closing this issue because it has been inactive for a few months.