Courses/C#/Test-Driven Development

    Test-Driven Development in Real Projects

    Write the test before the code. Let failing tests guide your design, producing cleaner, more reliable software with every iteration.

    What You'll Learn

    • • The Red-Green-Refactor cycle in practice
    • • Build features incrementally with iterative TDD
    • • Outside-In TDD: start from controllers, mock inward
    • • When TDD helps most and when it adds overhead

    🏗️ Real-World Analogy

    TDD is like building with LEGO instructions. Each step (Red) shows you the piece you need. You find it and snap it in (Green). Then you tidy up the build surface (Refactor). You never build blindly — every piece has a purpose defined before you place it.

    Red-Green-Refactor: The TDD Cycle

    Red: Write a test that fails. Green: Write the minimum code to pass it. Refactor: Clean up while keeping tests green. Repeat for each new behaviour.

    Red-Green-Refactor with ShoppingCart

    Build a shopping cart feature step by step using the TDD cycle.

    Try it Yourself »
    C#
    using Xunit;
    
    // Step 1: RED — Write a failing test first
    // We need a ShoppingCart that calculates totals with discounts
    
    public class ShoppingCartTests
    {
        // RED: This test FAILS because ShoppingCart doesn't exist yet
        [Fact]
        public void NewCart_HasZeroTotal()
        {
            var cart = new ShoppingCart();
            Assert.Equal(0m, cart.Total);
        }
    
        [Fact]
        public void AddItem_SingleItem_UpdatesTotal()
        {
            var cart = new ShoppingCart();
            cart.AddItem("Widget", 
    ...

    Iterative TDD: Growing Features

    Real TDD is iterative. Start with the simplest requirement, make it pass, then add the next. Each iteration extends your implementation without breaking previous tests.

    Iterative TDD — Password Validator

    Build a password validator one requirement at a time with TDD.

    Try it Yourself »
    C#
    using Xunit;
    using System;
    
    // TDD Workflow: Build a PasswordValidator step by step
    
    // ── Iteration 1: Basic length check ──
    public class PasswordValidatorTests_V1
    {
        [Theory]
        [InlineData("abc", false)]        // Too short
        [InlineData("abcdefgh", true)]    // 8 chars — valid
        [InlineData("", false)]           // Empty
        public void Validate_ChecksMinimumLength(string password, bool expected)
        {
            var validator = new PasswordValidator();
            var result = validator.Va
    ...

    Outside-In TDD

    Start from the outermost layer (API controller), mock dependencies, and work inward. Interfaces emerge naturally from what your tests need — producing clean architecture by design.

    Outside-In TDD — Order System

    Start from the controller, mock services, and let interfaces emerge from tests.

    Try it Yourself »
    C#
    using Moq;
    using Xunit;
    
    // Outside-In TDD: Start from the API controller, mock inward
    
    // ── Test the controller first ──
    public class OrderControllerTests
    {
        [Fact]
        public async Task CreateOrder_ValidRequest_Returns201()
        {
            // Arrange — mock the service layer
            var mockService = new Mock<IOrderService>();
            mockService.Setup(s => s.CreateOrderAsync(It.IsAny<CreateOrderDto>()))
                .ReturnsAsync(new Order { Id = 1, Status = "Created" });
    
            var contro
    ...

    Pro Tip

    TDD works best for business logic and domain rules. For UI code, integration tests, or exploratory prototyping, a "test-after" approach is often more pragmatic. Don't force TDD everywhere — use it where it gives the most value.

    Common Mistakes

    • • Writing too many tests at once — TDD means one failing test at a time
    • • Skipping the refactor step — code gets messy even when tests pass
    • • Testing implementation details — test behaviour, not internal structure

    Lesson Complete!

    You've mastered Test-Driven Development. Next, learn how to structure large applications with Clean Architecture.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service