Quick Index
Overview


Unit tests are simply program code (dtest) that tests (domain) program code.

We call them "unit tests" because we are testing units (objects/models).

Generally we tests something like:


The unit test name is not an exact science -- these are only suggested names.

General Unit Test Pattern 💡


Tests basically follow this "1-2-3" pattern:


Note: The software test "comparison" can be basic (print that allows a visual compare) or more sophisticated (e.g., showing "test passes", "test fails").

Blocker Bugs 🐞


What Are Blocker Bugs?


Blocker bugs are the enemy of coders:


Examples


A few examples of common blocker bugs:


Patterns


These nasty blocker bugs follow a couple patterns:


Avoiding Blocker Bugs 😊


The happy news is we can easily avoid blocker bugs.

We just need to to do things:


Smoke Tests


Purpose


"Smoke tests" are great initial (simple) tests that help to avoid dreaded blocker bugs.

The concept is to run the software and then just look for obvious smoke (blocker bugs).

They exercise the code more than testing it, with the purpose of being to validate that the software simply runs.

Smoke tests help assure the following:


Limitations:


Smoke and functional compared:


Examples



Functional Test


After smoke testing, we have "functional testing" -- e.g., "Is our software giving the correct answers?"

Functional tests compare actual results vs expected results.

Functional tests "cover" as many public methods as possible. Ideally, there is one or more functional tests for each public method.

Testing Lessons Learned


Start with 'Smoke Tests' to Find 'Blocker Bugs'


First make sure that simple "smoke tests" pass.

Continue with Functional Testing


After smoke tests are passing, then add functional tests (which compare "actual" vs "expected" results).

Do Not Put Test Code in Same Directory as Domain/Model Code


Graders and object will be using/testing our objects from "other" directories (and importing our files as needed) so we want to do similar. Otherwise, there is a good chance we'll miss bugs that they will hit (and these could be "blocker bugs").

If we put our test code in another directory (apart from our model/domain) then we will exercise/test required "imports" etc of our code.

By domain/model we mean our data structures (e.g. dynamic arrays, linked lists, trees, etc).

Test Objects (Not Just Primitives)


When testing a data structure we do not want to just test primitive element types like integers, strings, etc.

We also want to make sure our data structures work with "proper objects". These can be anything (e.g. customers, employees, stars, books, etc.).

We generally want to design the object types (classes) to have a unique key (e.g. customer number, employee number, star id, book ISBN, etc).

Equals Over '=='


Generally in object languages the operator "==" works for primitive values only (not proper objects).

So in your test code (and domain code) you should try to use the flavor an available version of "equals".

To support object equality, you will also likely need to implement "equals" in any object types (classes) you are using for tests.

Collections Take Special Care


We need to take special care when comparing collections.

We will need to verify that our equality checks are working for something like "collection1.equals(collection2)".

We may need to add helper/support methods to get these checks to work properly.

Test Code Styles


Overview


Test code can be simple to sophisticated.

It does not need to be sophisticated to be useful, especially for small projects.

Example Tests (Different Test Strategies)


These examples are in Java syntax but the ideas apply to other objects languages like JavaScript, etc.

Examples are here...

Simple Unit Test Examples


Overview


This page contains a couple simple unit test examples.

Examples


The examples are in pseudocode.

Convert them to your specific language (Js, Java, etc) to meet the syntax of your language. Especially note:


Example 1 -- Testing with Primitives


Example Pseudocode
Testing with primitives (e.g. integers, strings, doubles) is an okay way to get started testing. But see "lessons learned" on testing with "proper objects".
class DynamicArrayTest  {

	test_get_usingStrings() {

		let nm1 = 'Asha';
		let nm2 = 'Kofi';
		let dynamic = DynamicArray.newEmpty();
		dynamic.add(nm1);
		dynamic.add(nm2);
	
		var result, expected;
	
		result = dynamic.get(0);
		expected = nm1;
		this.show(result.toString());
		this.show(expected.toString());
	
		result = dynamic.get(1);
		expected = nm2;
		this.show(result.toString());
		this.show(expected.toString());
	
		//we could also test "first" and "last" the same way
	}
	
	//...
}



Example 2 -- Testing with Proper Objects


Example Pseudocode
You'll need to also code a testee object (to test with) -- in this example we use "Customer" -- download here for an example....
class DynamicArrayTest  {

	test_get_usingProperObjects() {

		let customer1 = Customer.fromFnameLnamePhoneZip('Kofi', 'Lee', '1112223333', 55100);
		let customer2 = Customer.fromFnameLnamePhoneZip('Asha', 'Woods', '9991231234', 55300);
		let dynamic = DynamicArray.newEmpty();
		dynamic.add(customer1);
		dynamic.add(customer2);

		var result, expected;

		result = dynamic.get(0);
		expected = customer1;
		this.show(result.toString());
		this.show(expected.toString());

		result = dynamic.get(1);
		expected = customer2;
		this.show(result.toString());
		this.show(expected.toString());
	}
	
	//...
}