nothingworksinc / ticketbeast

Back to the lesson videos:
https://course.testdrivenlaravel.com/lessons
552 stars 11 forks source link

All records are being deleted after running tests #83

Open bigweld86 opened 6 years ago

bigweld86 commented 6 years ago

Hi. So I've been running my tests using an SQLite "in memory" database. Since it's "in memory" records are not persistent, so I created a MySQL database and ran the migrations just to be able to have persistent data so I can see how everything is currently working (after running the tests). I created some records and inserted them into MySQL instance and checkout the pages that have been built so far, but every time I run the tests the data from MySQL DB is gone.

Is there any way to prevent that? can I play with persistent and have the SQLite instance for testing? I believe this is happening due to the fact that every time I run the tests the migrations are being triggered, right?

Thanks, Sebastian

jkniest commented 6 years ago

You should look at the phpunit.xml file. Especially this lines:

https://github.com/nothingworksinc/ticketbeast/blob/def3e0b6b2b2b9297027dd05072668733f4b9645/phpunit.xml#L35-L36

They will separate your testing database from your real database so you can have a persistent storage and all your tests are using a in-memory database :-)

bigweld86 commented 6 years ago

@jkniest that's exactly my current configuration at the moment of the issue:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>

        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
        <env name="DB_CONNECTION" value="sqlite" />
        <env name="DB_DATABASE" value=":memory:" />
    </php>
</phpunit>
LostKobrakai commented 6 years ago

Leaving the database clean is actually a desired behaviour. Tests should not leave any trails behind, because those could change the behaviour and therefore correctness of other tests. This is implemented by using database transactions (and rollbacks) to wrap around each test, so changes are never actually written to the db itself, but only exist within the transaction. So if you really want changes to stick around don't use the RefreshDatabase trait.

tnorthcutt commented 6 years ago

@LostKobrakai what @bigweld86 is saying, I think, is that though his config is set to use sqlite for testing, it's wiping his mysql database – which it shouldn't, unless I'm mistaken.

adamwathan commented 6 years ago

@bigweld86 Any chance you are using PHPStorm? I've seen other folks run into situations where PHPStorm was not actually using the environment variables from phpunit.xml due to a configuration issue 🤔

twosocks commented 6 years ago

The video here explain very well how to setup phpstorm to run unit/feature tests (not Browser tests) https://blog.jetbrains.com/phpstorm/2017/10/videos-testing-with-phpstorm/

I had a similar problem at the beginning and it was a simple misconfiguration problem. Try to double check again your config

bigweld86 commented 6 years ago

@adamwathan no, I'm using Sublime Text 3

roni-estein commented 6 years ago

Hi everyone, I know this course is a bit older, yet I’m still finding it quite helpful.

To Adam or anyone who has more testing experience, do you have any strategies for testing using mysql or larger databases? I was looking at this course while converting an old untested application to a tested one. It’s been quite helpful. However the tests are taking so long to migrate, even without the base seed data that its about a minute to run, even though there are only 20-30 tests done, and some tests will need the seed data which will radically increase the testing time. That and there are probably hundreds of tests yet to write.

At the outset it was mentioned that the tests would start out in-memory sqlite and transition. Anyone remember if and where those lessons are? Or if they didn’t make it into the course, anyone have any advice on best strategies for structuring the build up for situations like that? Or is the 15min-1 hour test suite inevitable on projects?

Thanks in advance for any advice.

Roni Estein

aphofstede commented 6 years ago

@roni-estein I run it with a separate, limited test-set / seed when in test env In my case a CSV seeder: $this->filename = __DIR__ . '/csvs/my_seed_data' . (\App::runningUnitTests() ? '_testing' : '') . '.csv'; This helps speed up things quite a lot, but writing tests now does require some knowledge of the data in the tests seed..

sandervanhooft commented 6 years ago

@roni-estein For complexer / larger table structures I'd manually pick what migrations and seeders to run prior to each test, instead of using RefreshDatabase.

For an example on how to trigger a migration, see here.

sandervanhooft commented 6 years ago

Using in-memory sqlite, picking the necessary migrations and factories (factory(SomeClass::class)->create();) instead of seeding the whole database is probably the most memory efficient and fast.

Bear in mind that this is about testing functionality, not performance. You'd need another setup for performance testing, which is a whole other cup of tea.

sandervanhooft commented 6 years ago

@roni-estein I'm assuming you're not testing against a production db.

roni-estein commented 6 years ago

@sandervanhooft, Those are great ideas, it might take a while to re-setup but I think just setting the tables I need to perform the specific tests would probably make a big difference. It's already a running application so I can't just test against existing data. It would be cool if I could.

However, I have nightly backups, I can spin up a database restore and test on those. I wasn't sure if there is an accepted strategy for that. It's medical with many ways to enter profiles, test results, notifications, claims etc. But it's not unit tested

I've been using refresh databases trait on each test, but that's building so testing each registration path is re-seeding the DB with tables and basic required data. But I could probably try and isolate migrations. Or spin up a testing server and test everything on yesterday's data with only the new migrations that need to run. So the tests basically don't migrate unless necessary.

Have you ever tried running tests on an already populated DB? Anyone have any posts/articles on something like that? Is there a "right way"?