Menu
Coddy logo textTech

Unit Testing (NUnit/xUnit)

Part of the Object Oriented Programming section of Coddy's C# journey — lesson 67 of 70.

challenge icon

Challenge

Easy

Let's complete your Library System project by adding unit tests! Testing is essential for ensuring your code works correctly and continues to work as you make changes. You'll create a dedicated test file that verifies the core functionality of your library system.

You'll continue working with your existing project structure, adding a new test file:

  • Book.cs: Keep your Book class with Id, Title, Author, IsAvailable, and the Borrow() and Return() methods.
  • User.cs: Keep your User class with borrowing tracking, MaxBooks constant, CanBorrow(), and methods for managing borrowed books.
  • Library.cs: Keep your Library class with borrowing logic, search methods, and the GetAllBooks() and GetAllUsers() methods.
  • LibraryTests.cs: This is your new test file! Create a test class that verifies your library system works correctly. You'll write test methods that check various scenarios and report whether each test passes or fails.
  • Program.cs: Your entry point that runs the tests and displays results.

Your test class should include methods that test these scenarios:

  • TestBookBorrow - Verify that borrowing an available book succeeds and changes its availability
  • TestBookBorrowUnavailable - Verify that borrowing an already-borrowed book fails appropriately
  • TestUserBorrowingLimit - Verify that users cannot borrow more than 3 books
  • TestBookReturn - Verify that returning a borrowed book works correctly
  • TestSearchByAuthor - Verify that searching by author returns the correct books

Each test method should return a boolean indicating whether the test passed. Create a simple test runner that executes all tests and prints the results.

You will receive the following inputs:

  • Number of test scenarios to run (1-5, corresponding to the tests listed above)

For each test that runs, print the result in the format:

{TestName}: {PASS|FAIL}

After all tests complete, print a summary:

--- Test Summary ---
Passed: {count}
Failed: {count}
Total: {count}

For example, if the input is:

3

The output should be:

TestBookBorrow: PASS
TestBookBorrowUnavailable: PASS
TestUserBorrowingLimit: PASS
--- Test Summary ---
Passed: 3
Failed: 0
Total: 3

Another example with all 5 tests:

5

The output should be:

TestBookBorrow: PASS
TestBookBorrowUnavailable: PASS
TestUserBorrowingLimit: PASS
TestBookReturn: PASS
TestSearchByAuthor: PASS
--- Test Summary ---
Passed: 5
Failed: 0
Total: 5

Your tests should create fresh instances of Book, User, and Library for each test to ensure isolation. This way, one test's state doesn't affect another. Think of each test as a self-contained verification of a specific behavior in your system!

Try it yourself

using System;
using System.Collections.Generic;

namespace LibrarySystem
{
    class Program
    {
        public static void Main(string[] args)
        {
            // Read library name
            string libraryName = Console.ReadLine();
            
            // Create a Library instance with the library name
            Library library = new Library(libraryName);
            
            // Read number of commands
            int numCommands = Convert.ToInt32(Console.ReadLine());
            
            // Process commands
            for (int i = 0; i < numCommands; i++)
            {
                string commandLine = Console.ReadLine();
                string[] parts = commandLine.Split('|');
                string command = parts[0];
                
                if (command == "ADD_BOOK")
                {
                    string bookId = parts[1];
                    string bookTitle = parts[2];
                    string bookAuthor = parts[3];
                    
                    Book book = new Book(bookId, bookTitle, bookAuthor);
                    library.AddBook(book);
                    Console.WriteLine($"Added: {bookTitle}");
                }
                else if (command == "ADD_USER")
                {
                    string userName = parts[1];
                    int memberId = Convert.ToInt32(parts[2]);
                    
                    User user = new User(userName, memberId);
                    library.RegisterUser(user);
                    Console.WriteLine($"Registered: {userName}");
                }
                else if (command == "BORROW")
                {
                    string bookId = parts[1];
                    int memberId = Convert.ToInt32(parts[2]);
                    
                    string result = library.BorrowBook(bookId, memberId);
                    Console.WriteLine(result);
                }
                else if (command == "RETURN")
                {
                    string bookId = parts[1];
                    int memberId = Convert.ToInt32(parts[2]);
                    
                    string result = library.ReturnBook(bookId, memberId);
                    Console.WriteLine(result);
                }
                else if (command == "SEARCH")
                {
                    string searchType = parts[1];
                    List<Book> results = new List<Book>();
                    
                    if (searchType == "title")
                    {
                        string searchValue = parts[2];
                        results = library.SearchByTitle(searchValue);
                    }
                    else if (searchType == "author")
                    {
                        string searchValue = parts[2];
                        results = library.GetBooksByAuthor(searchValue);
                    }
                    else if (searchType == "available")
                    {
                        results = library.GetAvailableBooks();
                    }
                    else if (searchType == "borrowed")
                    {
                        results = library.GetBorrowedBooks();
                    }
                    
                    if (results.Count == 0)
                    {
                        Console.WriteLine("No books found");
                    }
                    else
                    {
                        foreach (Book book in results)
                        {
                            Console.WriteLine($"{book.Title} by {book.Author}");
                        }
                    }
                }
                else if (command == "STATUS")
                {
                    List<Book> allBooks = library.GetAllBooks();
                    List<Book> availableBooks = library.GetAvailableBooks();
                    List<User> allUsers = library.GetAllUsers();
                    List<Book> borrowedBooks = library.GetBorrowedBooks();
                    
                    Console.WriteLine("--- Library Status ---");
                    Console.WriteLine($"Total Books: {allBooks.Count}");
                    Console.WriteLine($"Available: {availableBooks.Count}");
                    Console.WriteLine($"Total Users: {allUsers.Count}");
                    Console.WriteLine($"Books Borrowed: {borrowedBooks.Count}");
                }
            }
        }
    }
}

All lessons in Object Oriented Programming