Rollback database after integration (Selenium) tes

2019-02-01 14:01发布

问题:

Does anyone have any suggestions for a best practice or preferred way of rolling back database transactions made from an integration test framework such as Selenium?

Here is our current situation: We have a .net web project with a number of unit tests which work fine in our unit test environment - each test inherits a parent class which opens a transaction in the [SetUp], and rolls back the transaction in the [TearDown]. After each test, our unit test database is restored back to the original state.

However, things change once we get to our integration environment. Our continuous integration server automatically compiles our commits and pushes them out to a test server, so that the server always runs on the most up to date code. We've also setup a Selenium instance to automate user interaction with the site. The selenium tests basically communicate with an existing Selenium server, and tell the server things like, "Launch a browser and go to http://testsite/TestPage.aspx - enter text 'abc' into form field with id 'def' - assert new page contains text 'xyz'"

Each test is run in a similar manner to our vanilla unit tests, but with an important exception: any changes made by Selenium are done in a completely different thread/application, and therefore we can't (I *think we can't, at least) roll them back in the test teardown.

We've yet to come to a good solution for this. Right now we're at a point where we're using a SqlCommand to execute a sql statement to backup the database, then at the end of the test, we're setting the database to single user, dropping the current db, and restoring the old copy - this is less than ideal, because that effectively kills the application that was attached to the DB, and requires us to yet again re-initialize the app.

Is this a problem that has been solved before? Any advice would be awesome.

Thanks!

回答1:

We are running a drop/create-table script before every test. This is quite fast and ensures that nothing is left from previous tests.

PS: We are using NHibernate, which creates this script on the fly and run the test on Sqlite in memory, it's lightspeed. But if we switch to SqlServer it's still quite fast.



回答2:

It's a tough problem and the solution is typically unique for every app. Until the major frameworks adopt a "recommended approach", this will continue to be a pain.

My best recommendation: plan for this usage at the start of your app. Include APIs that clean up after the DB is reset from underneath the app (ie: reset caches).



回答3:

There is a project called Amnesia (more docs, recent code) that is designed specifically for this scenario. It simplifies the process of using the MSDTC TransactionScope to rollback test changes. (Usage will require moderately invasive changes to data access in most applications, especially those not already using MSDTC.)