Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are those unit tests fine?

I'm trying to grasp test driven development, and I'm wondering if those unit tests is fine. I have a interface which looks like this:

public interface IEntryRepository
{
    IEnumerable<Entry> FetchAll();
    Entry Fetch(int id);
    void Add(Entry entry);
    void Delete(Entry entry);
}

And then this class which implements that interface:

public class EntryRepository : IEntryRepository
{
    public List<Entry> Entries {get; set; }

    public EntryRepository()
    {
        Entries = new List<Entry>();
    }

    public IEnumerable<Entry> FetchAll()
    {
        throw new NotImplementedException();
    }

    public Entry Fetch(int id)
    {
        return Entries.SingleOrDefault(e => e.ID == id);
    }

    public void Add(Entry entry)
    {
        Entries.Add(entry);
    }

    public void Delete(Entry entry)
    {
        Entries.Remove(entry);
    }
}

Theese are the unit tests I have written so far, are they fine or should I do something different? Should i be mocking the EntryRepository?

[TestClass]
public class EntryRepositoryTests
{
    private EntryRepository rep;

    public EntryRepositoryTests()
    {
        rep = new EntryRepository();
    }

    [TestMethod]
    public void TestAddEntry()
    {
        Entry e = new Entry { ID = 1, Date = DateTime.Now, Task = "Testing" };
        rep.Add(e);

        Assert.AreEqual(1, rep.Entries.Count, "Add entry failed");
    }

    [TestMethod]
    public void TestRemoveEntry()
    {
        Entry e = new Entry { ID = 1, Date = DateTime.Now, Task = "Testing" };
        rep.Add(e);

        rep.Delete(e);
        Assert.AreEqual(null, rep.Entries.SingleOrDefault(i => i.ID == 1), "Delete entry failed");
    }

    [TestMethod]
    public void TestFetchEntry()
    {
        Entry e = new Entry { ID = 2, Date = DateTime.Now, Task = "Testing" };
        rep.Add(e);

        Assert.AreEqual(2, rep.Fetch(2).ID, "Fetch entry failed");
    }
}

Thanks!

like image 616
alexn Avatar asked Dec 23 '22 12:12

alexn


2 Answers

Just off the top of my head...

Although your testing of add really only tests the framework:

  • You've got adding 1 item, that's good
  • what about adding LOTS of items (I mean, ridiculous amounts - for what value of n entries does the container add fail?)
  • what about adding no items? (null entry)
  • if you add items to the list, are they in a particular order? should they be?

likewise with your fetch:

  • what happens in your fetch(x) if x > rep.Count ?
  • what happens if x < 0?
  • what happens if the rep is empty?
  • does x match performance requirements (what's it's algorithmic complexity? is it within range when there's just one entry and when there's a ridiculously large amount of entries?

There's a good checklist in the book Pragmatic Unit Testing (good book, highly recommended)

  • Are the results right?
  • Are all the boundary conditions CORRECT
    • Conform to an expected format
    • Ordered correctly
    • In a reasonable range
    • Does it Reference any external dependencies
    • Is the Cardinality correct? (right number of values)
    • does it complete in the correct amount of Time (real or relative)
  • Can you check inverse relationships
  • Can you cross check the results with another proven method
  • Can you force error conditions
  • Are performance characteristics within bounds
like image 129
Steven Evers Avatar answered Dec 31 '22 14:12

Steven Evers


Here's some thoughts:

Positive

  • You're Unit Testing!
  • You're following the convention Arrange, Act, Assert

Negative

  • Where's the test to remove an entry when there's no entry?
  • Where's the test to fetch an entry when there's no entry?
  • What is supposed to happen when you add two entries and remove one? Which one should be left?
  • Should Entries be public. The fact that one of your asserts calls rep.Entries.SingleOrDefault suggests to me you're not constructing the class correctly.
  • Your test naming is a bit vague; typically a good pattern to follow is: {MethodName}_{Context}_{Expected Behavior} that remove the redundancy "test" redundancy.

As a beginner to TDD I found the book Test-Driven Development By Example to be a huge help. Second, Roy Osherove has some good Test Review video tutorials, check those out.

like image 30
Gavin Miller Avatar answered Dec 31 '22 15:12

Gavin Miller