Monday, September 27, 2010

Test Driven Approach - Positive Impact for Developers - Workshop III (Part B)

Now, lets us try to compile and run the test again. As expected, it won't compile at all. We need refactoring to the unit tests at Calculator.Tests as such: -
using Calculator.Core;
using Calculator.Presenter;
using NUnit.Framework;

namespace Calculator.Tests
{
    public class CalculatorMockView : ICalculatorView
    {
        public string Result { get; set; }
        public string Formula { get; set; }
    }
    
    [TestFixture]
    public class CalculatorTester
    {
        private Presenter.Calculator _calculator;
        private ICalculatorView _view;

        [SetUp]
        public void SetUp()
        {
            _view = new CalculatorMockView();
            _calculator = new Presenter.Calculator(_view);
        }

        [TestCase("6", "6")]
        [TestCase("5 + 6", "11")]
        [TestCase("3 - 2", "1" )]
        [TestCase("5 * 6", "30")]
        [TestCase("12 / 6", "2")]
        [TestCase("5 + 6%", "5.3")]
        [TestCase("reciproc(2)", "0.5")]
        [TestCase("pow(2,3)", "8")]
        [TestCase("sqrt(4)", "2")]
        [TestCase("12 / 6 / 8", "0.25")]
        [TestCase("reciproc(2,3,2)", "", ExpectedException = typeof(UnexpectedCalculationException))]
        [TestCase("sqrt(4, 21)", "", ExpectedException = typeof(UnexpectedCalculationException))]
        [TestCase("A + B + C", "", ExpectedException = typeof(IncompatibleDataTypeFormulaException))]
        [TestCase("HelloWorld(2,3,2)", "", ExpectedException = typeof(UnexpectedCalculationException))]
        [TestCase("2 3 2", "", ExpectedException = typeof(UnexpectedCalculationException))]
        public void EvaluationTest(string formula, string expected)
        {
            _view.Formula = formula;
            _calculator.Evaluate();
            Assert.AreEqual(_view.Result, expected);
        }
    }
}

And Calculator.Core.Tests as such: -
using NUnit.Framework;

namespace Calculator.Core.Tests
{
    [TestFixture]
    public class CalculatorTests
    {
        readonly Calculator _calculator = new Calculator();

        [TestCase("6", "6")]
        [TestCase("5 + 6", "11")]
        [TestCase("3 - 2", "1")]
        [TestCase("5 * 6", "30")]
        [TestCase("12 / 6", "2")]
        [TestCase("5 + 6%", "5.3")]
        [TestCase("reciproc(2)", "0.5")]
        [TestCase("pow(2,3)", "8")]
        [TestCase("sqrt(4)", "2")]
        [TestCase("12 / 6 / 8", "0.25")]
        [TestCase("reciproc(2,3,2)", "", ExpectedException = typeof(UnexpectedCalculationException))]
        [TestCase("sqrt(4, 21)", "", ExpectedException = typeof(UnexpectedCalculationException))]
        [TestCase("A + B + C", "", ExpectedException = typeof(IncompatibleDataTypeFormulaException))]
        [TestCase("HelloWorld(2,3,2)", "", ExpectedException = typeof(UnexpectedCalculationException))]
        [TestCase("2 3 2", "", ExpectedException = typeof(UnexpectedCalculationException))]
        public void EvaluationTest(string formula, string expected)
        {
            Assert.AreEqual(expected, _calculator.Calculate(formula));
        }
    }
}

Above, I have also added a few additional test cases where necessary. Now lets us compile and test run them. As expected, they are still failed.


Before we proceed, to correct all these tests, let us revisit what have we done so far?
1. We created solution based on some (small) fundamental architecture design.
2. We created a wire frame demonstrated how this look like conceptually.
3. We then created some unit tests focuses on "how we think the public API would be useful and clean". (API Usability Concern from consumer perspective.)
4. We introduce new projects (core) to ensure we provide better separation of business core logic. (Separation of Concern and Single Responsibility)
5. We then decide again how is the public API of the new project just added would look like. (API Usability again)
6. We implemented the presenter logic, wire up the UI wire frame, and the Core logic classes. (some UI design patterns were introduced for unit tests and better code separation).
7. We refactor the some API within its implementation and its corresponding unit testings in Calculator.Tests and Calculator.Core.Tests. (Refactoring based on needs).

Now, all the above just came naturally as we do our development in TDD fashion.

So, the next workshop, we will be aiming to clear all these unit tests.

No comments:

Post a Comment