6
votes

I have an API project running at localhost:8000 connected to a test database, and I have a front-end angular app running at localhost:9000. How do I reset the database after each front-end test case run? I'm using Protractor for my front-end E2E testing. I do not want to mock or stub the whole backend. Although that will make my test run faster, however, every user interaction will result changes to the server states and followed by several more requests to the same server endpoints, stubbing these endpoints with different returns at different points might be too much code than just talking to a real server. I'd rather reset the database to an initial state or flush all the tables.

One potential way to do it is to write my front-end E2E test suite in my API project. Since now it's ran by the backend test runner, it could easily reset the database before each test case. But I'd rather keep my tests in my front-end project, since my api will also serve other clients, not just the browser client. And since my backend is in php and uses Phpunit for testing, while I'm using Protractor to test my front-end, integrating it into the backend seems to be a bit misplaced.

Have you run into this problem and what's your solution? How do you coordinate the two projects in your E2E (or integration?) test?

2
I guess one way would be to provide the support for "resetting" in your backend, and call that API for every new test. - New Dev
@NewDev That sounds dangerous though. But I guess you can secure it by guarding it with an environment check. The other way is to figure out a way to reset the database in the onPrepare callback for Protractor. I'm wondering if there are better ways still. Thanks for answering. - randomor
Absolutely, this should only be in your testing environment and not in Prod :) Btw, this is still not a substitute for mocking, just as it is not a substitute for unit-testing, but for e2e things like that are sometimes required. - New Dev
@NewDev I'm wondering if this is pretty common among E2E tests especially cross services, to have an endpoint that will reset the target service. - randomor
I can't really answer about how common this is. E2E tests are difficult to automate and very dependent on the organization where you are working. - New Dev

2 Answers

1
votes

I got into the same problem. My solution is to add a "reset" api end point to restore the database to its state before E2E test starts.

We are using ASP.NET WebApi to build the RESTful service. Here is my code structure.

[HttpGet]
[Route("reset")]
public IHttpAction Reset(){
    // check and remove records added in the e2e tests

    // check and restore the records modified in the e2e tests

}

So an api call to this test/reset method helps restore the backend database into its original state. We can place the call inside afterAll() (if you are using JasmineJS). Or you can just do a manual reset by making that GET call from Postman or Fiddler.

Sometimes, I have multiple reset api methods to call. So that I can test and reset by function groups. Like, perform e2d tests on user management functions and reset that part of data, and then move on to the next function.

One thing to mention is that if the primary key on a table is sequenced, the removal of data added in the test will break that sequence. Make sure our tests are not to "expect" on that primary key.

The whole goal is to be able to rerun the e2e tests and get the same result.


And of course, if allowed, another good way out is to backup the database before our e2e test and restore it after the test finishes. Manual, stupid, but sometimes convenient and sufficient to allow our e2e test to rerun.

1
votes

I went for writing all E2E tests inside the API project after going the client side route unsuccessfully. The trade-offs:

  1. API has all the factories and models that could be used to bootstrap the test cases. If testing just from the client-side, I have to re-create the model relationships and factories to make it work, and have to track all the changes from API models.

  2. I have to manually setup the client-side to talk to the testing api environment every time before running the E2E test. And also manually set the api server to be in testing mode. Because you need to keep the actual API web server running somewhere so client can hit.

  3. At this time it is still hard to figure out a way to move this very customized test setup to the cloud, and thus integrate with a continuous integration server, because client and api are two separate project. But I finally have some client-side E2E testing running on my local machine, which is better than no tests.