-
Notifications
You must be signed in to change notification settings - Fork 321
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
Test methods influence each other through session #100
Comments
You should drop the session each test instead of killing the entire chromedriver process. Plus, why aren't you mocking the session in your tests? Or set the session to Array |
Mocking the session is not possible since the browser is a different process. |
This is an issue for me as well. The session and the cache persist from test to test, and there's no way to use "array" for either. So all those files need to be deleted between every test. I'm currently achieving this by setting them both to "file" and then using the following in my /**
* Set up our testing environment
*
* @return void
*/
public function setUp()
{
parent::setUp();
exec('git clean -fxd ' . storage_path());
} (This deletes all the session and cache files.) |
@Sieabah You can't use array because as already mentioned, the actual tests execute under a different process. Probably the same reason you cannot use in-memory sqlite. One way to circumvent these problems is to use a physical sqlite file (if you want to use sqlite), set both cache and session drivers to use the database and use the DatabaseMigrations trait to continually reset your database before every test. Of course, this means you would need the migration files for both cache and session tables, even if you will be using something else on a different environment like production. Because of this though (running on a separate process), I just realized that this prevents me from setting up my application environment such as mocking services and disabling middleware since anything that happens in my DuskTestCase classes won't exist during the actual test runs. Any way around this? |
@georaldc Just wanna make sure you didn't miss that I gave code above to circumvent the problems without using database driver for session/cache. Also, for way faster testing, you can simply run your migrations and seeds once beforehand, creating a This ends up looking like this (in /**
* Set up our testing environment
*
* @return void
*/
public function setUp()
{
parent::setUp();
// Reset the sqlite testing database
// http://www.chrisduell.com/blog/development/speeding-up-unit-tests-in-php/
copy(database_path('prepared.sqlite'), database_path('database.sqlite'));
// Reset the cache and sessions.
exec('git clean -fxd ' . storage_path('framework/cache'));
exec('git clean -fxd ' . storage_path('framework/sessions'));
} |
@JVMartin yup, saw that. Was just giving an alternative solution. Running migrations happen very quickly for me so I am not too concerned about it affecting speed (maybe if I have a ton of tests would I look for a different approach, such as your suggestion so thanks for that). I have bigger speed related problems though when using dusk, which can be found in a separate issue I created a few days ago - #98 |
As @georaldc pointed out, the issues with the new architecture are deep, and prevent all manner of integration testing that used to be possible. For instance: public function testForgotPasswordFlow()
{
Mail::fake();
// Use the forgot password form.
$this->browse(function(Browser $browser) use ($user) {
$browser->visit(new HomePage)
->clickLink('forgot password?')
->type('@forgot-password-email', '[email protected]')
->press('Email Me')
->waitForText(trans('auth.forgot-pass'));
});
Mail::assertSent(ResetPasswordLinkEmail::class);
} The assertSent() will always fail. This kind of testing no longer works because the application itself is now completely decoupled from the testbed. How are we supposed to do integration tests now? |
@JVMartin regarding mails you could configure laravel to submit mails to mailtrap, then use their API to verify that the mail has been sent when executing your Dusk tests. There is this great But I guess the more Laravel way would be to implement what I've sketched in #152. That would also be a lot faster than sending actual mail over the network to mailtrap and pulling the data back into your test case for verification. And you could make it work for anything where you can set the driver in the |
Another work-around is using https://github.com/themsaid/laravel-mail-preview and then fetching the HTTP from there. Of course don't enable it on production systems. Drawbacks: hard to parse the subjects line (it's inside a HTML comment) and you only have access to one (the last) email. It saves the emails to a text file, similar to the Dusk screenshots. |
I found this topic while searching about
So I thought: why am I not facing this issue? The only thing that came to mind was the following:
Each test will have a clean database because of these lines that I have on |
I agree! I just moved sessions to the database and this is a nice workaround. The tests pass immediately. > php artisan session:table
> php artisan migrate Edit SESSION_DRIVER=database EDIT: Note this only works if you use |
@fschwaiger that seems to be a very clever solution, thank you! |
How about Laravel Passport that uses JWT cookies instead of sessions? |
A quick fix: Inside your $browser->driver->manage()->deleteAllCookies(); I'm going to submit a PR for this as well. |
Another option until my PR is approved. Add this to your root public function browse(Closure $callback)
{
parent::browse($callback);
static::$browsers->first()->driver->manage()->deleteAllCookies();
} |
For localStorage tokens like those you might set using a JWT solution, you could do the following
You can execute scripts on the browser using |
@smtlk That localStorage solution doesn't work for me, I get an error:
|
Closing this issue because it's already solved, old or not relevant anymore. Feel free to reply if you're still experiencing this issue. |
@inxilpro I appreciate the |
Same things here, I suspect I didn't find a universal solution to handle all sessions drivers, you have to make your own. For me I had to change It would be great to have an artisan command to delete all sessions, regardless of session driver. |
Test methods should not influence each other. However, the following two methods share the same session and the second will fail, because the user is already logged in.
The issue is fixed if the last line,
closeAllButPrimary()
is changed tocloseAll()
:The text was updated successfully, but these errors were encountered: