diggingforfire
diggingforfire

Reputation: 3399

Unit testing with multiple inputs

I've been trying to wrap my head around unit testing and I'm trying to deal with unit testing a function whose return value depends on a bunch of parameters. There's a lot of information however and it's a bit overwhelming..

Consider the following:

I have a class Article, which has a collection of prices. It has a method GetCurrentPrice which determines the current price based on a few rules:

public class Article
{
    public string Id { get; set; }
    public string Description { get; set; }
    public List<Price> Prices { get; set; }

    public Article()
    {
        Prices = new List<Price>();
    }

    public Price GetCurrentPrice()
    {
        if (Prices == null)
            return null;

        return (
            from
            price in Prices

            where

            price.Active &&
            DateTime.Now >= price.Start &&
            DateTime.Now <= price.End

            select price)
            .OrderByDescending(p => p.Type)
            .FirstOrDefault();
    }
}

The PriceType enum and Price class:

public enum PriceType
{
    Normal = 0,
    Action = 1
}

public class Price
{
    public string Id { get; set; }
    public string Description { get; set; }
    public decimal Amount { get; set; }
    public PriceType Type { get; set; }
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public bool Active { get; set; }
}

I want to create a unit test for the GetCurrentPrice method. Basically I want to test all combinations of rules that could possibly occur, so I would have to create multiple articles to contain various combinations of prices to get full coverage.

I'm thinking of a unit test such as this (pseudo):

[TestMethod()]
public void GetCurrentPriceTest()
{
    var articles = getTestArticles();
    foreach (var article in articles)
    {
        var price = article.GetCurrentPrice();
        // somehow compare the gotten price to a predefined value
    } 
}

Upvotes: 3

Views: 3856

Answers (4)

Pritam Karmakar
Pritam Karmakar

Reputation: 2801

I think you need datadriven testing. In vsts there is an attribute called Datasource, using it you can send a test method multiple test cases. Make sure you don't use multiple asserts. Here is one MSDN link http://msdn.microsoft.com/en-us/library/ms182527.aspx

Hope this will help you.

Upvotes: 2

Ivan
Ivan

Reputation: 1284

new test for each startup condition and single assert,f.e.

[Test]
public void GetCurrentPrice_PricesCollection1_ShouldReturnNormalPrice(){...}

[Test]
public void GetCurrentPrice_PricesCollection2_ShouldReturnActionPrice(){...}

and also test for boundaries

for unit tests i use pattern

MethodName_UsedData_ExpectedResult()

Upvotes: 2

Darin Dimitrov
Darin Dimitrov

Reputation: 1038820

You are not using a repository in this example so there's no need to mock anything. What you could do is to create multiple unit tests for the different possible inputs:

[TestMethod]
public void Foo()
{
    // arrange
    var article = new Article();
    // TODO: go ahead and populate the Prices collection with dummy data


    // act
    var actual = article.GetCurrentPrice();

    // assert
    // TODO: assert on the actual price returned by the method
    // depending on what you put in the arrange phase you know
}

and so on you could add other unit tests where you would only change the arrange and assert phases for each possible input.

Upvotes: 4

John Saunders
John Saunders

Reputation: 161773

You do not need multiple asserts. You need multiple tests with only a single assert each.

Upvotes: 2

Related Questions