How it works
A useful test chooses inputs that can reveal a mistake in the rule. For a range check, values in the middle are necessary but insufficient: an implementation with the wrong inclusive or exclusive boundary can still accept every middle example. Add values exactly at the boundaries and just outside them so the intended transitions become visible.
An executable check compares an observed result with an independently written expectation. If the expectation is computed by repeating the same expression as the implementation, both can share the same error. This lesson uses a tiny table of concrete cases rather than a testing framework, so the core idea can run inside the app. The same structure can later become unit tests in a larger project.
Walk through the example. The IsValidPercentage function accepts integers from zero through one hundred, inclusive. The cases cover negative one, zero, one hundred, and one hundred one. Each row contains an input and a manually chosen expected result. The loop compares actual and expected values, prints PASS for each correct case, and maintains a final count of successful checks.
Watch the boundary. Four passing checks do not prove every possible program property. They establish evidence for the stated boundary rule. Choose additional tests when the contract includes parsing, null input, overflow, or interaction with other rules. Keep test names and failure output tied to observable behavior so a failed check tells you which requirement needs investigation.
Practice independently. Write a function for a shipping-weight band with an inclusive lower bound and exclusive upper bound. Prepare a table containing both boundaries, adjacent values, and one middle value. Intentionally introduce a wrong comparison operator and confirm that a boundary check fails. Restore the function, then describe one important behavior outside the range rule that would need its own independent set of tests.
A working example
using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
bool IsValidPercentage(int value) => value >= 0 && value <= 100;
var cases = new[] { (Input: -1, Expected: false), (Input: 0, Expected: true), (Input: 100, Expected: true), (Input: 101, Expected: false) };
int passed = 0;
foreach (var item in cases)
{
bool correct = IsValidPercentage(item.Input) == item.Expected;
if (correct) passed++;
Console.WriteLine($"{item.Input}:{(correct ? "PASS" : "FAIL")}");
}
Console.WriteLine($"passed:{passed}/{cases.Length}");
Expected output
-1:PASS 0:PASS 100:PASS 101:PASS passed:4/4
Write expectations independently and include values on both sides of every decision boundary.