Question

I am writing automated test cases in Visual Studio 2017 test frame work. I am testing the ‘create user’ part of a web API. A user needs to be created with a unique email address. Once a user is created they cannot be deleted.

Is there way to write automated (run on check-in) test cases, that need unique input data for each test run?

In the example below Username, must be unique on each call. Username can be up to 30 characters long.

ProcessStudent(
    string StudentAuthId, 
    string FirstName, 
    string MiddleName, 
    string LastName, 
    string UserName, 
    string UserPassword
);

(My thoughts) Since there is no way (I can think of) to make this test atomic, there needs to be unique input values each time the test is run. This could be done by appending some version of a time stamp to the UserName passed in. I am not sure this is the best way of doing this so I am asking this question.

Was it helpful?

Solution 3

I took the suggestion of cr3. I used the Bogus lib for C#. Using the Bogus lib and Microsoft.VisualStudio.TestTools.UnitTesting I was able to create random test data for each test that needed it. I used the word “Purge” in the random data so that it could be found and removed later. I wanted to post an example, since that is what I was looking for originally.

[TestInitialize]
    public void Initialize()
    {
        //Replace a formatted string with random numbers #, letters ?, or * random number or letter
        var faker = new Faker("en");

        StudentAuthIdRandom = new Bogus.Randomizer().Replace("???:???:???-Purge");
        FirstNameRandom = new Bogus.Randomizer().Replace("????-Purge");
        MiddleNameRandom = new Bogus.Randomizer().Replace("?????-Purge");
        LastNameRandom = new Bogus.Randomizer().Replace("??????-Purge");         
        UserNameRandom = new Bogus.Randomizer().Replace("????????-Purge");
        UserPasswordRandom = new Bogus.Randomizer().Replace("?*****-Purge");
    }

Note: I have learned from the other answers that what I am doing is integration (not unit) testing and there should be a dedicated DB for this. Having a dedicated DB for this work was not an option for me so I used data values that could easily be found and removed for the dev BD we are using.

thank you for all the responses and suggestions

OTHER TIPS

It is common to need unique values when testing. So, you might like to look for a library that already provides that functionality for you.

If you can't find an existing library, then you could consider rolling your own with reusability in mind:

  • You could start with generating a unique integer. The first implementation could use the timestamp as you suggested. If that sometimes causes collisions, then you might want to only initialize a counter with a timestamp and increment it on every call. If you run your tests in multiple threads or multiple processes, then you could adjust accordingly.
  • You could continue with generating a unique string. The first implementation could use the stack to include the filename and line number of the caller in the string, to which you could append the unique integer in the previous bullet. If that generic string makes it hard to troubleshoot, then you could parameterize the function to take a prefix or a suffix to make it more specific.
  • You could be even more specific with generating a unique username. If generating a unique string violates some username constraints, this function could change the string accordingly. For example, if the filename, line number and unique integer in the unique string are separated with dashes but that character is not permitted in a username, then you could either parameterize the unique string function to take a separator character or you could just substitute the dashes in the string.

By building a library, it can be easily unit tested so that other tests can use it with confidence. Also, by reusing functions, you could incrementally improve it as you encounter potential collisions. For example, if you improve the unique integer function then both the unique string and unique username in the above design will benefit; not to mention all the tests that use this library.

Your issue is likely that your processing code is coupled tightly to your DB, try decoupling and things will get much easier:

class StudentProcessor
{
     Func<string, bool> CheckUsernameIsUnique;
     public StudentProcessor(Func<string, bool> checkUsernameIsUnique)
     {
         CheckUsernameIsUnique = checkUsernameIsUnique;
     }

     public ... ProcessStudent(...)
     {
         CheckUsernameIsUnique(username);
         ...
     }
}

It is now much easier to test what happens here

void Test()
{
     var processor = new StudentProcessor(x => {"username1", "username1"}.Contains(x));
     processor.ProcessStudent(...);
}

What happened here, is that your unit testing problems has shown you that your current implementation has tight coupling which makes it hard to maintain. This is not a problem with unit testing, it is its main benefit :)

It sounds like you are writing integration tests that require a live Web API. If that is the case, it is perfectly fine to use the live web API for testing purposes, but you need to control the database.

Before each test, wipe the database clean. Then insert exactly the data you need for the test. Run the test. Assert. Rinse and repeat.

If are not testing the integration of your application and the API, then you need to decouple those calls from your core business logic, usually by defining an interface for the Web API object and mocking it in your other tests.

I realize you said you cannot control the database. If that is the truth, then you shouldn't be including the database as part of the tech stack under test.

Licensed under: CC-BY-SA with attribution
scroll top