Table of Contents
This table mirrors the sidebar subtopics and helps you jump to any section quickly. It gives a structured roadmap of NUnit concepts from setup to best practices. Use it to return to attributes, fixtures, or runners when needed. A clear ToC keeps learning efficient and reduces context switching.
Start -> Topic -> Example -> Practice
// Example learning path
// Setup -> Attributes -> Parameterized tests -> Practice
Real-world use case: Sharing deep links to sections in team documentation.
1. NUnit Overview
NUnit works on the .NET runtime and supports unit testing across libraries and applications. It uses attributes to identify tests and configure behavior. NUnit integrates with IDEs and CI systems via adapters. It is lightweight, fast, and widely supported.
NUnit Framework
|
Attributes + Assertions
|
Test Runner
[Test]
public void Add_ReturnsSum()
{
Assert.AreEqual(5, Add(2, 3));
}
Real-world use case: Validating business rules in a finance API.
2. Project Setup
Create a test project and reference the main project assembly. The assembly holds your compiled classes under test. Add the NUnit package and a test adapter for your IDE or CI. Run a simple test to confirm everything is connected.
App Project -> Build -> Test Project
\-> NUnit Packages
dotnet new nunit -n MyApp.Tests
cd MyApp.Tests
dotnet add reference ../MyApp/MyApp.csproj
dotnet add package NUnit3TestAdapter
dotnet test
Real-world use case: Bootstrapping tests for a new microservice.
3. Attributes & Fixtures
NUnit relies on attributes to declare tests, fixtures, and categories. Use namespaces to group your fixtures by feature. Fixtures can include setup methods to reduce duplication. Clear naming helps test discovery in large solutions.
[TestFixture]
|
[Test] methods
[TestFixture]
public class PaymentTests
{
[Test]
public void Validate_ReturnsTrue_ForValidCard()
{
Assert.IsTrue(Payment.Validate("4111"));
}
}
Real-world use case: Organizing tests for multiple payment providers.
4. Assertions
Assertions validate outcomes and define test success criteria. Use the most specific assertion available to keep failures clear. NUnit supports constraint-based assertions for expressive checks. Clear assertion messages help debugging when a test fails.
Expected vs Actual
| |
+-- Assert
[Test]
public void CalculateTax_ReturnsExpected()
{
var tax = Calculator.Tax(200m, 0.05m);
Assert.That(tax, Is.EqualTo(10m));
}
Real-world use case: Ensuring tax calculations stay precise.
5. Parameterized Tests
Parameterized tests help cover multiple scenarios without duplicating code. Use TestCase for simple values or TestCaseSource for complex datasets. This keeps your test suite compact and easier to maintain. It also highlights boundary values in a consistent format.
Input A -> Test
Input B -> Test
Input C -> Test
[TestCase(1, 0)]
[TestCase(10, 5)]
[TestCase(50, 10)]
public void Discount_ByCount(int items, int expected)
{
Assert.AreEqual(expected, DiscountRules.Calculate(items));
}
Real-world use case: Verifying discount tiers for an e-commerce platform.
6. Setup & Teardown
NUnit offers setup and teardown to prepare test data and clean resources. Use setup/teardown attributes like [SetUp], [TearDown], [OneTimeSetUp]. Keep them short to avoid hidden dependencies. When tests run in parallel, shared state must be protected.
OneTimeSetUp
|
SetUp -> Test -> TearDown
|
OneTimeTearDown
[SetUp]
public void BeforeEach()
{
_calculator = new Calculator();
}
[TearDown]
public void AfterEach()
{
_calculator = null;
}
Real-world use case: Cleaning temporary files created during a test run.
7. Test Runners & Adapters
NUnit tests run via a test runner like dotnet test or IDE runners. Install the NUnit adapter so discovery works correctly in Visual Studio. The runner uses metadata to find [Test] methods and execute them. Reports can be exported to CI dashboards for visibility.
IDE/CLI Runner
|
NUnit Adapter
|
Test Results
dotnet test --logger "trx"
# Run in CI and publish results
Real-world use case: Enforcing quality gates in a CI pipeline.
8. Best Practices
Write tests that are deterministic and independent of external systems. Use clear naming to express what the test verifies. Keep tests fast by avoiding sleeps and unnecessary I/O. Organize fixtures by feature and use categories for filtering.
Clean Test Suite
+ Clear Names
+ Fast Runs
+ Isolated Data
| Practice | Why it Helps |
|---|---|
| One Arrange block | Clarity |
| Test data builders | Reuse and readability |
| Categories | Selective runs |
[Test]
public void CalculateTax_WhenZero_ReturnsZero()
{
Assert.That(Calculator.Tax(0m, 0.1m), Is.EqualTo(0m));
}
Real-world use case: Keeping enterprise test suites maintainable over years.
9. Sample Project: Inventory Rules
Build a sample project that validates inventory thresholds. Use a fixture to group stock and reorder tests. Add parameterized tests for different reorder points. The sample demonstrates clean setup and focused assertions.
Inventory -> Rule Engine -> Reorder?
[TestFixture]
public class InventoryRulesTests
{
[TestCase(2, 5, true)]
[TestCase(10, 5, false)]
public void ShouldReorder(int stock, int threshold, bool expected)
{
Assert.AreEqual(expected, InventoryRules.ShouldReorder(stock, threshold));
}
}
Real-world use case: Preventing stock-outs in a warehouse system.
10. FAQs
FAQs address common NUnit questions about setup, assertions, and adapters. They also clarify when to use NUnit versus other frameworks. Keep answers practical and link back to core sections. Use FAQs to reduce repetitive support questions.
Question -> Answer -> Reference
// FAQ snippet
// Q: Can NUnit run in CI?
// A: Yes, via dotnet test and adapters.
Real-world use case: Helping teams standardize their testing toolchain.
11. Interview Questions
Interview questions evaluate your ability to explain NUnit usage clearly. They cover attributes, fixtures, assertions, and test discovery. Use real-world examples to show your experience with CI. Explain trade-offs between NUnit and other frameworks.
Question -> Approach -> Example
- How does NUnit discover tests?
- What is the purpose of TestCase?
- Why use an adapter in Visual Studio?
- How do you structure fixtures in large solutions?
// Sample answer snippet
// "I use TestCase to cover multiple inputs with the same logic."
Real-world use case: Preparing for QA automation and backend interviews.
12. MCQ Quiz
This quiz checks key NUnit concepts like attributes and assertions. It is a fast way to confirm understanding after reading. Use the quiz to identify topics you should revisit. Provide correct answers when distributing to learners.
Question -> Option A/B/C -> Answer
- Which attribute marks a test method? ([Test])
- What is a fixture? (Class grouping tests)
- Which runner executes NUnit tests? (dotnet test)
- Which attribute supplies multiple inputs? ([TestCase])
- What should tests avoid? (External I/O)
// Quiz scoring
var score = answers.Count(x => x.IsCorrect);
Real-world use case: Short assessments during training sessions.
13. Summary of Key Points
NUnit offers a rich set of attributes, fixtures, and assertions for unit testing. Parameterized tests reduce duplication and increase coverage. Setup and teardown keep tests clean and repeatable. Test runners and adapters integrate NUnit with IDEs and CI. Following best practices keeps the suite maintainable.
NUnit + Good Practices -> Reliable Test Suite
// Summary checklist
// 1) Clear fixtures
// 2) Expressive assertions
// 3) Fast runners
Real-world use case: Release readiness checks before deploying.
14. Downloadable Resources (ZIP, PPT, DOC)
Provide offline resources for learners. Include a ZIP with sample NUnit tests, a PPT for presentations, and a DOC with exercises. Keep files versioned alongside the tutorial so they stay current. Use consistent naming for easy discovery.
Resources
|- NUnitSamples.zip
|- NUnitSlides.pptx
|- NUnitExercises.docx
// Placeholder links
// [Download ZIP] [Download PPT] [Download DOC]
Real-world use case: Facilitating classroom labs without internet access.
15. Glossary (Tooltips)
This glossary lists the tooltip terms used on the NUnit page. It helps you quickly refresh definitions while writing tests. Hover over terms in sections to see these descriptions. Update the glossary as your testing vocabulary grows.
Term -> Definition -> Example
| Term | Tooltip Description |
|---|---|
| NUnit | Open-source .NET testing framework with attributes, assertions, and runners. |
| .NET runtime | Execution environment for C# that manages memory and runs code. |
| Attribute | Metadata applied to code, used by NUnit to mark tests and lifecycle hooks. |
| Assembly | Compiled .NET output containing code, metadata, and resources. |
| Namespace | Logical container to organize types and avoid naming conflicts. |
| Test Fixture | Class grouping related tests with shared setup. |
| Assertions | Checks comparing expected vs. actual results. |
| Parameterized Tests | Same test logic executed with multiple inputs. |
| Setup/Teardown | Lifecycle hooks that run before or after tests. |
| Test Runner | Tool that discovers and executes tests, reporting results. |
// Glossary usage example
// "Use [TestCase] to create parameterized tests."
Real-world use case: Standardizing testing terminology across teams.
To Become Best coder Practice this
Practice these NUnit-focused questions to improve test design. Each question includes inputs, outputs, constraints, and a hint. Use NUnit attributes and assertions when writing your answers. Mix easy, medium, and hard tasks for balanced learning.
Problem -> Test -> Assert -> Review
Easy (5)
-
Problem: Test that Add(2,3) returns 5.
Input/Output: Input: 2,3 Output: 5.
Example: In: 2,3 → Out: 5.
Constraints: Integers only.
Hint: Use Assert.AreEqual. -
Problem: Test that IsEven(4) returns true.
Input/Output: Input: 4 Output: true.
Example: In: 4 → Out: true.
Constraints: n ≥ 0.
Hint: Use modulo. -
Problem: Test that Reverse("") returns empty string.
Input/Output: Input: "" Output: "".
Example: In: "" → Out: "".
Constraints: Length ≤ 200.
Hint: Handle empty as valid. -
Problem: Test that Clamp(5,1,10) returns 5.
Input/Output: Input: 5,1,10 Output: 5.
Example: In: 5 → Out: 5.
Constraints: min ≤ max.
Hint: Compare with min and max. -
Problem: Test that SafeDivide(10,0) throws.
Input/Output: Input: 10,0 Output: exception.
Example: In: 10,0 → Out: exception.
Constraints: divisor can be 0.
Hint: Use Assert.Throws.
Medium (5)
-
Problem: Parameterized test for tax rates 0%, 5%, 10%.
Input/Output: Input: rate, Output: expected tax.
Example: In: 100,0.05 → Out: 5.
Constraints: rate 0-1.
Hint: Use [TestCase]. -
Problem: Test that a validator rejects usernames shorter than 3 chars.
Input/Output: Input: "ab" Output: false.
Example: In: ab → Out: false.
Constraints: length ≤ 20.
Hint: Use boundary tests. -
Problem: Test that checkout applies free shipping for totals ≥ 50.
Input/Output: Input: 50 Output: free shipping.
Example: In: 50 → Out: free.
Constraints: total ≥ 0.
Hint: Assert on shipping fee. -
Problem: Test that a cache returns stored value within 1 minute.
Input/Output: Input: key, Output: value.
Example: In: key → Out: value.
Constraints: Use fake clock.
Hint: Inject time provider. -
Problem: Test that inventory reorder triggers when stock below threshold.
Input/Output: Input: stock=2, threshold=5 Output: true.
Example: In: 2,5 → Out: true.
Constraints: non-negative stock.
Hint: Use parameterized tests.
Hard (5)
-
Problem: Test concurrency safety for a thread-safe queue.
Input/Output: Input: 100 enqueue/dequeue → Output: empty queue.
Example: In: 100 ops → Out: empty.
Constraints: Use parallel tasks.
Hint: Assert final count. -
Problem: Test a retry policy stops after max retries with specific exception.
Input/Output: Input: max=3 → Output: 3 attempts.
Example: In: 3 → Out: 3 attempts.
Constraints: Avoid delays in tests.
Hint: Inject a delay strategy. -
Problem: Test that a rule engine selects highest priority rule.
Input/Output: Input: rules+input → Output: selected rule.
Example: In: A,B → Out: A.
Constraints: Priority unique.
Hint: Assert on chosen rule id. -
Problem: Test that a scheduler fires a job exactly once at time.
Input/Output: Input: time=10:00 → Output: one call.
Example: In: 10:00 → Out: 1 call.
Constraints: Use fake clock.
Hint: Verify invocation count. -
Problem: Test that a parser rejects malformed JSON with a specific exception type.
Input/Output: Input: malformed JSON → Output: exception.
Example: In: "{bad" → Out: JsonException.
Constraints: No external network.
Hint: Use Assert.Throws with type.
// Practice scaffold
// Use NUnit attributes: [Test], [TestCase], [SetUp].
Real-world use case: Preparing for NUnit-focused interviews and assessments.