diesel-rs / diesel

A safe, extensible ORM and Query Builder for Rust
https://diesel.rs
Apache License 2.0
12.74k stars 1.07k forks source link

Allow for testing migration down functions #1584

Open moore3071 opened 6 years ago

moore3071 commented 6 years ago

It's currently very easy to run into a poorly written migration where the down function doesn't correctly undo the migration. Diesel's documentation suggests the use of redo for testing this, but unless a project is testing this via CI, it's likely that faulty down functions will only be noticed when they're run. Even worse, it may be difficult to track down which migration was faulty. It would be cool if Diesel could include a command that starts with two blank databases, runs through the migrations step by step while redoing the migrations on the first database and checking that it is equivalent to the second database. A naive bit of pseudocode:

let db1 = get("database1")
let db2 = get("database2")
for x in migrations:
        db1.run_migration(x)
        db2.run_migration(x)
        db1.redo(x)
        assert_eq(db1,db2) # e.g. for Postgres, diff the pg_dump of the two
moore3071 commented 6 years ago

Instead of using two databases and dumping database info, it would make a lot more sense to use Diesel's ability to print the schema. This only gives table structure, but would be much easier to implement.

An obviously needed feature in a binary implementing this would be the ability to exclude the testing of specified migrations.

mehcode commented 5 years ago

Even something simple like:

db = get("database")
for x in migrations:
  db.run(x)

for _ in migrations:
  db.redo()

for x in migrations:
  db.run(x)

Would at least run each down and catch any left over entities.

I'm thinking diesel migration check to be a good command name.

weiznich commented 5 years ago

@mehcode This should be doable by using the methods provided by the Migration in diesel-migrations.

markus2330 commented 6 days ago

I fully agree that the diesel command should support this. Does redo and redo -a have any other purpose than testing?

If no, I would propose that diesel migration redo and diesel migration redo -a actually checks that the database is exactly as it was before and warns the user, if the database was left in a different state (ideally with a diff what changed).

weiznich commented 6 days ago

@markus2330 We are happy to receive contributions for this. Otherwise there are many things that are desirable to have, but where nobody has the time or motivation to implement it.