Sign up ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

((Using "users" as an example to represent one of many record types))

An application with user tracking typically has a User table. Many, if not all, companies mandate that a User record should never be actually deleted. Instead, a discrimating field "isDeleted" should be added. The other possibility is a shadow table that tracks deleted users and its own set of questions which shouldn't be addressed here.

So in general, to retrieve a list of users, I may have a method like so:

public ICollection<User> GetUsers() {
    return Users.Where(x => x.isDeleted == false);
}

So I have an SDK which wraps a web service which call domain services which depend on data access which hits my database. The eventuallity is something like so:

public void DeleteUser(int id) {
    var user = Users.Where(x => x.id == id).Single();
    user.isDeleted = true;
    user.SaveDatShiz();
}

So what about my Integration Test? I have an Integration Test something like so:

public void TestUserCreation() {
    Dependency.CreateUser(user);
    var integratedUser = Dependency.GetUserBySomething(user.Something);
    Assert.AreEqual(integratedUser, user, "wut?");
    Dependency.DeleteUser(integratedUser.id); //Clean up!
}

The key above is that my Integration Test thinks it is cleaning up, but in reality, my Production Database has three times more fake test users than actual users. The table is SUPER bloated from running Integration Tests on Deployment in a Continuous Deployment environment.

So how do I let my Integration Tests ACTUALLY Delete a user? I'm not asking for a code answer, I'm asking for a architecturally correct answer.

E.G.: Should I create an endpoint that actually does a delete, but require a key that only the Integration Test knows? That seems messy...

E.G.2: Should I get access directly to the production database and run delete queries against it? (Lol, totally lawl no.)

E.G.3: Nobody else worries about this, so I shouldn't (Non-Refundable!!! I mean.. Not Acceptable!!!!)

share|improve this question

1 Answer 1

Firstly, I'd try to not run tests on true production databases if possible, but I know this cannot always be avoided.

In my tests of this type, I ensure the database is as expected with a range of simple AddEntry, DeleteEntry, AssertEntry and AssertEntryCount routines that either insert, delete, assert the content of, or assert the expected count of rows in tables with specified fields and values.

These have a TableName parameter and then a ParamArray parameter called ColumnsAndValuesAndOptionalConnectString (as well as a couple of straight SQL query overloads) that expects field names, then the same number of values and finally an optional connection string.

In your case, I'd have one (or as few as possible) test that creates a new user and if it succeeds the cleanup does actually drop the user created.

The rest should refer to a single (or again as few as possible) "Integration Testing" user that is normally marked as deleted, but that user is undeleted while tests are performed upon it.

To answer your question: "Should I provide a way to really delete a user?" If you don't want to access the database directly to "run delete queries against it", you have to choose between creating new test users for every test or creating some code path that actually deletes users. If you do go for the second option you can make the user deletion routine only available to your test code by a number of means, and depending upon your development environment, you may be able to avoid showing it on your public API.

Perhaps the most straightforward solution is to identify test users in some explicit way and define a DeleteTestUser public API that is documented to only delete test users, but does so completely.

share|improve this answer
1  
Assuming the deletion routine was on the other side of an HTTP endpoint normally accessed via an SDK but not necessarily, what are some of your ideas on how to make that endpoint only available to my test code? –  Suamere Jun 15 at 13:55
    
Right, that is a harder scenario. My first thought is a conditional build that only includes the endpoint for testing purposes. It could be that the WSDL, etc. only includes the endpoint when retrieved by the testing machine's IP address. –  Mark Hurd Jun 15 at 17:47

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.