Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollback test data #15

Closed
warrence opened this issue Apr 20, 2016 · 16 comments
Closed

Rollback test data #15

warrence opened this issue Apr 20, 2016 · 16 comments

Comments

@warrence
Copy link

Hi, may i know how should i rollback the created data during dread test?

@ddelnano
Copy link
Owner

Have you taken a look at the example in the wiki? There is an entire laravel example there (includes rolling back the database).

@warrence
Copy link
Author

warrence commented Apr 20, 2016

Yes i do. Maybe i should explain my problem further.

I have a create new user function, when i run dredd it will take the example in my apiary.apib and create the new user, so the second time i run dredd again it said email already used. So i was thinking maybe hook files db transaction only rollback any data created within the hook files only?

So i do another test, instead of rollback the created data, i tried to delete the user "foo@bar.com" in hook files so that the email are not duplicated when i run dredd test, and rollback deletion after dredd, however foo@bar.com doesn't not deleted and my dredd still give error saying email already used, but it works if i remove the db begin transaction and roll back in aftereach and beforeeach.

Below are my hook file

<?php

use Dredd\Hooks;
use App\Models\User;
use Illuminate\Support\Facades\Artisan;

require __DIR__ . '/../vendor/autoload.php';

$app = require __DIR__ . '/../bootstrap/app.php';

$app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();

Hooks::beforeEach(function(&$transaction) use ($app){
    $transaction->request->headers->Authorization = "Bearer {eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjExLCJpc3MiOiJodHRwOlwvXC9hcGkuY3N0cG9zLmRldlwvc2lnbmluIiwiaWF0IjoxNDYxMTI5MDI0LCJleHAiOjE0NjIzMzg2MjQsIm5iZiI6MTQ2MTEyOTAyNCwianRpIjoiNzc1M2EwZTMyMjRmYzFjMjg3ZGM0YTM1NDE0ODhiYjUifQ.g4RPDvmIjCdYMuqlVYEwjuROeEmuIs_a1oRhbWXCsOU}";
});

Hooks::beforeAll(function (&$transaction) use ($app)
{
    $app->make('db')->beginTransaction();

});

Hooks::afterAll(function (&$transaction) use ($app)
{
    $app->make('db')->rollback();
});

Hooks::before('Users > Create New User', function (&$transaction)
{

    $user = User::whereEmail('foo@bar.com');
    $user->forceDelete();

});

@ddelnano
Copy link
Owner

So here is what you need to be careful about. Anything that happens in a database transaction can only be seen by inside the same database connection that the transaction was created. If you use migrations for rolling back your issues will go away. Otherwise you need to make sure that your hooks file and your application code all have access to the same database connection.

@ddelnano
Copy link
Owner

Let me know if that makes sense. If not I can clarify.

@warrence
Copy link
Author

<?php

use Dredd\Hooks;
use App\Models\User;
use Illuminate\Support\Facades\Artisan;

require __DIR__ . '/../vendor/autoload.php';

$app = require __DIR__ . '/../bootstrap/app.php';

$app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();

Hooks::beforeEach(function (&$transaction) use ($app)
{
    $transaction->request->headers->Authorization = "Bearer {eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjExLCJpc3MiOiJodHRwOlwvXC9hcGkuY3N0cG9zLmRldlwvc2lnbmluIiwiaWF0IjoxNDYxMTI5MDI0LCJleHAiOjE0NjIzMzg2MjQsIm5iZiI6MTQ2MTEyOTAyNCwianRpIjoiNzc1M2EwZTMyMjRmYzFjMjg3ZGM0YTM1NDE0ODhiYjUifQ.g4RPDvmIjCdYMuqlVYEwjuROeEmuIs_a1oRhbWXCsOU}";
    DB::connection('mysql')->beginTransaction();

});

Hooks::afterEach(function (&$transaction) use ($app)
{
    DB::connection('mysql')->rollBack();
});

Hooks::before('Users > Create New User', function (&$transaction)
{

    User::create([
        'name'  => 'warrence',
        'email' => 'warrence@warrence.com'
    ]);

});

I change transaction db to mysql now which is the one i use in the application, and also put a user creating in the hook files when api Users > create new user is call, so should have 2 user being created when dredd is run, one is the one created in hook files "warrence@warrence.com" and the one from the application "foo@bar.com", but only "warrence@warrence.com" that created in hook files being roll back, and "foo@bar.com" still there.

@ddelnano
Copy link
Owner

So what is happening is your hooks are using a database connection that is using transactions, which is why the warrence@warrence.com is being rolled back. However, your app is NOT using the same connection, hence it is not in the database transaction, which means that the data never gets rolled back.

But essentially Laravel's base database class Illuminate\Database\Capsule\Manager has the ability to set a global database connection (via a static property). If you make sure that gets set it should work properly (because all database connections will be the same one and will be inside the transaction).

So the project that I have done this previously was not a laravel one so I used the Illuminate\Database\Capsule class directly but there exists a setAsGlobal() method which does exactly what I described (sets the connection as a static property). The link was to a trait but that trait gets used in the Manager class.

If you are still having trouble after that I can tweak your code to do what I just described, however, I probably wouldn't have time to help until the weekend.

@warrence
Copy link
Author

@ddelnano Thanks for your advise, i tried capsule manager but i dunno how to make it works with dredd test, please show me some code sample how to make it works in rollback transaction in application code in the hook files when you free. Thanks.

@ddelnano
Copy link
Owner

Ok I will try to have that sample for you on Saturday or Sunday.

@ddelnano
Copy link
Owner

In the mean time if you run your migrations in the before each and rollback the migrations in the after each that could work so that you can atleast get something working.

@warrence
Copy link
Author

@ddelnano i was wondering is it possible to use Illuminate\Foundation\Testing\DatabaseTransactions or Illuminate\Foundation\Testing\DatabaseMigrations inside hook files?

@warrence
Copy link
Author

Thanks @ddelnano

@ddelnano
Copy link
Owner

Actually now that I think about this more, you will not be able to use transactions for this. There is no way that your application and the hooks can share the same database connection. I apologize for misleading you.

The hooks run in a separate server (completely different php execution context) than your app. So you must use migrations.

@ddelnano
Copy link
Owner

@warrence Did you try using migrations?

@warrence
Copy link
Author

@ddelnano yes it works well. For now I only have around 10 API function to test so every time it will research database and apply seed, it definitely slow down the test becoz I put it in the aftereach. I'm thinking how if I run seeding only without migrate in its own function using "after", and only seed the effected table, wonder if it works or not, but this gonna be lots of writing in the hook files.

@warrence
Copy link
Author

@ddelnano my mistake, seeding doesn't reset data, so still have to use migrate:refresh --seed.

@ddelnano
Copy link
Owner

Ok I'm closing this since the resolution is you need to use migrations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants