TDD Introduction

4 minute read

by Peter Daukintis

Test Driven Development

This is a basic introduction to test-driven development describing related technologies in a simple, straightforward way. The learning curve can sometimes appear steep due to the range of associated technologies and architectural concepts that need to be understood. This post is a quick overview with some simple examples.

Basic Principles

TDD supports agile processes and coping with changing business requirements. It does this by enabling and promoting sound, flexible architectures which support unit testing. The test frameworks this allows, in turn, enables refactoring by providing confidence that existing functionality is not being broken. It supports a ‘clear separation of concerns’ via inversion of control patterns (http://www.martinfowler.com/articles/injection.html).  This enables dependencies to be easily replaced, promotes flexible architectures and enables runtime composition of logical components.

Dependencies

        public IEnumerable<Stuff> GetFilteredStuff(string filter)
        {
            DatabaseLayer dbl = new DatabaseLayer();
            var stuff = dbl.GetStuffFromDB();
            return stuff.Where(stuff => stuff.Name.startsWith(filter));
        }

 

This code illustrates a fixed dependency on the concrete database layer class. This prevents creation of a unit test without a database.

Using an interface we can remove the dependency:

        public IEnumerable<Stuff> GetFilteredStuff(string filter, IDatabaseRepository repository)
        {
            if (repository.AllowsFiltering())
            {
                var stuff = repository.GetStuffFromDb();
                return stuff.Where(s => s.Name.StartsWith(filter));
            }
            return null;
        }

Now the dependency is gone and we can unit test the method by providing a stub class which implements the IDatabaseRepository interface.

        [TestMethod]
        public void GetFilteredStuff_GivenValidFilter_ReturnsCorrectFilteredResult
        {
            IDatabaseRepsitory db = new StubDatabaseRepository();
            var result = db.GetFilteredStuff("Bob", db);

            // Assert expected result
        }

Unit Testing

So, working this way I can test each individual unit of logic. This promotes a flexible architecture and single responsibility classes and methods. If we were to test the original method with the database dependency by supplying a known database this would be integration testing.

Tools

As TDD has become more popular a network of support tools has flourished which really enable the viability of TDD. These are the main categories:

Categories:

Updated:

Comments