Jon
Jon

Reputation: 40032

Added functionality broke my tests - very simple logic too

I have code similar to this:

public List<string> Expected = new List<string>();
public int SpecifiedID;

public DataIn(int ID, string Value)
{
  Expected.Add(Value);
  //if (ID == SpecifiedID)
  //Expected.Clear();  

  //Need to add this but my tests that do something like      
  //CollectionAssert.AreEqual(new[] { "2", "4", "6", "8" }, logic.Expected);
  //all fail as Expected is empty.
}

//Example Test
[Test]
public void NewTestFunction()
{
   MyClass logic = new MyClass();   
   logic.SpecifiedID = 4;

   logic.DataIn(1,"2"); 
   logic.DataIn(2,"4"); 
   logic.DataIn(3,"6"); 
   logic.DataIn(4,"8"); 

   //This will FAIL if Expected.Clear is added in the class.
   CollectionAssert.AreEqual(new[] { "2", "4", "6", "8" }, logic.Expected);
}

This is simplified a lot however I have tests that check the validity of the Expected contents when DataIn is called. However I now have realised I have to clear Expected after every DataIn call. This has broken my tests obviously as there is nothing in it to assert against.

Any suggestions on how to keep the tests that validate the contents but also allow me to empty the collection?

Upvotes: 0

Views: 112

Answers (4)

guillaume31
guillaume31

Reputation: 14064

When the SpecifiedID is matched everything has to be cleared

This is one test. Instantiate your object. Give it a SpecifiedId of X. Call DataIn() on it with Y as a first parameter and then with X as a first parameter. Assert that Expected is empty. Simple.

when the next call is made it starts adding data to it again ready for validation

This is another test. Instantiate your object. Give it a SpecifiedId of X. Repeatedly call DataIn() on it never using X as an ID. Assert that Expected contains the passed values. Simple.

Two requirements, two tests. Really, I can't see what's the big deal here.

Upvotes: 1

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236218

The answer is simple - your code does not pass your test. I.e. it does not behave as expected (you describe expected behavior in your test). So, code should change - remove call to Expected.Clear(). Or think about what you expect from your code.

UPDATE (for case when expectations changes):

public void ShoulHaveAllDataInWhenIdIsNotSpecifiedID()
{
   MyClass logic = new MyClass();   
   logic.SpecifiedID = 3;

   logic.DataIn(1,"2"); 
   logic.DataIn(2,"4");     

   CollectionAssert.AreEqual(new[] { "2", "4" }, logic.Expected);
}

[Test]
public void ShoulClearAllDataWhenSpecifiedIDPassed()
{
   MyClass logic = new MyClass();   
   logic.SpecifiedID = 3;

   logic.DataIn(1,"2"); 
   logic.DataIn(2,"4"); 
   logic.DataIn(3,"6");     

   CollectionAssert.AreEqual(new[] { }, logic.Expected);
}

Also consider doing behavior testing instead of state testing. By providing mocks to your class you can check how it interacts with them. I.e. check what data passed to your class dependency.

Upvotes: 2

tvanfosson
tvanfosson

Reputation: 532465

Initialization to known good state should be part of your test/class setup method. From your description, though, it seems like you may have too much coupling between your tests or that your tests are testing too much at one time. Each test, with appropriate set up, should be independent and ideally able to run in parallel. Typically this means that each is running against a different instance of the class under test and you don't have dependencies on global data, or at least those dependencies are read-only so you can set it once for all tests.

Upvotes: 1

Tigran
Tigran

Reputation: 62246

Why do not just change test function. Create a new test function:

[Test]
public void NewTestFunction()
{
    Data("Bla"); 

    //Test for something


    Expected.Clear();
}

If this is not what you're asking for, please clarify.

Upvotes: 0

Related Questions