Quick Index
Video


Here is a video that goes along with this page.

Challenge Description


This is an example challenge that we'll step through together.

For this challenge the coder will apply smoke tests to a City unit (class) in an effort to look for showstopper bugs.

The coder is provided with:


The challenge is to use the unit test to identify bugs, and then resolve the bugs. A "bug summary" must be prepared.

We'll refer back, to the previous chapter for information on the City as needed.

First grab the example code: Download....

Then open your favorite IDE or code editor and code along with this example. Make sure your project classpath includes "src".

Project Directory Structure


Here is the project directory structure with primary players noted.

Note that classpath (Java) is also called build path (Eclipse) or source folder (IntelliJ).
+---srcclasspath
| +---model | | +---geography | | \---GeoLocation.java | | \---City.javaUnit | +---test | +---cases | +---geography | \---CityTest.javaUnit
Test
|


Action Plan


We will assume that the unit has no compiler errors.

Prerequisite - Resolve Warnings
Before we jump to the unit test, we assure the unit is "clean".

This means resolving compiler errors and warnings.
+---src
|   +---model
|   |   +---geography
|   |       \---GeoLocation.java
|   |       \---City.javaResolve any compiler warnings
|   +---test
|       +---cases
|           +---geography
|                  \---CityTest.java
|
Step #1 - Compiler Errors
We look for compiler errors in unit test, which points us to bugs in unit.
+---src
|   +---model
|   |   +---geography
|   |       \---GeoLocation.java
|   |       \---City.javaFix corresponding
bugs
| +---test | +---cases | +---geography | \---CityTest.javaLook for compiler
errors
|
Step #2 - Runtime Exceptions/Errors
We run the unit test, which points us to bugs in unit.
+---src
|   +---model
|   |   +---geography
|   |       \---GeoLocation.java
|   |       \---City.javaFix runtime
bugs
| +---test | +---cases | +---geography | \---CityTest.javaRun unit test |


Starting the Bug Hunt


Let's start the fun.

Here is the provided code for this example: Download....

Open your favorite IDE or code editor and code along with this example.

Resolving Compiler Warnings (Unit)


Overview


We know from introductory coding that we must fix all compile errors before code is usable.

But bugs also lurk behind compiler warnings. Therefore, we want to resolve all warnings. We'll learn (later) that there are rare cases where we will suppress (ignore) certain warnings.

For this example we assume compiler errors have already been taken care of -- thus we focus on warnings.

Resolving Compiler Warnings in Unit


Let's open up the unit source code file and resolve any compiler warnings.

Bug: Ignoring Parameter
A compiler warning is shown in the unit source code -- a method parameter is being ignoring (not used).
private MyCity(String nm,Param "nm"
is not used
double lat, double lon) { this.location.setLatitude(lat); this.location.setLongitude(lon); }
Bug Fix: Use Parameter
Simple bug fix -- set the corresponding ivar.

The unit now has no warnings.
private MyCity(String nm,
		double lat, double lon) {
	this.name = nm;Bug fix
	this.location.setLatitude(lat);
	this.location.setLongitude(lon);
}

Bug Search via Compiler Errors (in Unit Test)


Overview


We now look for bugs in the unit that cause compiler errors in the unit test.

Note that actual error messages (text) may vary slightly by IDE/editor.

Bug: Import (Package) Cannot Be Resolved


Compiler Error
In unit test, the compiler error is "model.geography cannot be resolved".
package test.cases.geography;

import model.geographyThe import
cannot be
resolved
.City;
Investigation
When we peek at the unit code we discover that the dir/package name is incorrect.

Recall that the required/expected name is "geography"
+---src
|   +---model
|   |   +---mygeographyIncorrect
package
name
| | \---GeoLocation.java | | \---MyCity.java
Bug-Fix: Fix Package Name
We simply correct the package name as shown.
+---src
|   +---model
|   |   +---mygeography geographyCorrect the
package
name
| | \---GeoLocation.java | | \---MyCity.java


Bug: Import (Class) Cannot Be Resolved


Compiler Error
In unit test, the compiler error is "model.geography.City cannot be resolved".
package test.cases.geography;

import model.geography.CityThe import
cannot be
resolved
;
Investigation
We discover that the unit file name is incorrect.

Recall that the required/expected filename is "City.java"
+---src
|   +---model
|   |   +---mygeography
|   |       \---GeoLocation.java
|   |       \---MyCity.javaIncorrect
filename
Bug-Fix Part 1: Fix File Name
Correct the filename.
+---src
|   +---model
|   |   +---mygeography geography
|   |       \---GeoLocation.java
|   |       \---MyCity.java City.javaCorrect the
filename
Bug-Fix Part 2: Fix Class Name
  • Open City.java
  • Change all occurrences of "MyCity" to expected class name "City"
class MyCity CityCorrect class name
(all occurrences)


Bug: Type Not Visible


Compiler Error
In unit test, the compiler error is "The type model.geography.City is not visible".
package test.cases.geography;

import model.geography.CityThe type
is not visible
;
Investigation
In the unit, we find that we are missing the access modifier public.
class CityMissing
keyword
'public'
{
Bug-Fix: Add Keyword 'public'
Make bug-fix shown.
publicAdd 'public'
class City


Bug: Method Not Visible


Compiler Error
In unit test, the compiler error is "The method newInstance() from the type City is not visible".
/**
 * Conduct a smoke test for the construction of
 * a City with no args
*/
public void test_newInstance()  {
	prn("\n-- test_newInstance --");
	City city = City.newInstance()Method
not visible
; prn(city.toString()); }
Investigation
In the unit we identify the problem shown.
protectedMethod is
not public
static City newInstance()
{
Bug-Fix: Add Keyword 'public'
In unit, make bug-fix shown.
protected publicChange to public
static City newInstance()
{

Bug Search via Running Unit Test


Overview


Running the unit test will help us expose bugs in the unit.

Note that actual error messages (text) may vary slightly by IDE/editor.

Bug: NullPointerException in 'test_newInstance'


Runtime Exception!
Run the unit test.

An exception occurs, as shown.
Exception NullPointerExceptionA null pointer
exception occurred
test_newInstance(CityTest.java:16)The file and line
number of the exception
main(CityTest.java:41)
Inspect Exception
  • Open up CityTest.java
  • Go to the provided line number (from prev step)
public void test_newInstance()  {
	prn("\n-- test_newInstance --");
	City city = City.newInstance();
	prn(city.toString());The exception
occurred here!
}
Infer Bug Location
  • Per the null pointer exception, the var 'city' must be null.
  • Therefore, "City.newInstance()" must be returning null
public void test_newInstance()  {
	prn("\n-- test_newInstance --");
	City city = City.newInstance();#2 - therefore this
must return null
prn(city#1 - the exception tells us
that 'city' must be null
.toString()); }
Inspect Bug
  • Open City.java
  • Go to the method "newInstance"
  • The bug is obvious, as shown.
/** Returns new City object with
name "Unnamed" and location (0, 0) */
public static City newInstance() {
	return null;Oops this is
a problem
}
Fix Bug
Fix bug as shown
/** Returns new City object with
name "Unnamed" and location (0, 0) */
public static City newInstance() {
	return null;
	return fromNameLatLong("Unnamed", 0, 0);Corrected code
}


Bug: NullPointerException in Constructor


Runtime Exception!
Run the unit test.

An exception occurs, as shown.
Exception NullPointerExceptionA null pointer
exception occurred
City.<init>(City.java:38)The file and line
number of the exception
City.fromNameLatLong(City.java:23) City.newInstance(City.java:29) CityTest.test_newInstance(CityTest.java:15) CityTest.main(CityTest.java:41)
Inspect Exception
  • Open up City.java
  • Go to the provided line number (from prev step)
private City(String nm, double lat, double lon) {
	this.name = nm;
	this.location.setLatitude(lat);The exception
occurred here!
this.location.setLongitude(lon); }
Infer Bug
Per the exception, we infer that the ivar 'location' must be null
private City(String nm, double lat, double lon) {
	this.name = nm;
	this.locationIvar "location"
must be null
.setLatitude(lat); this.location.setLongitude(lon); }
Fix Bug
Not initializing an ivar is a common bug. Ivars are often initialized during construction.

We fix the bug as shown.
private City(String nm, double lat, double lon) {
	this.name = nm;
	this.location = GeoLocation.newInstance();Add this line
to initialize the
ivar
this.location.setLatitude(lat); this.location.setLongitude(lon); }


Clean Run


We run the test again.

No exceptions occur! 🤸🏽

The smoke tests are running which gives us confidence that code will run.
-- test_newInstance --
Unnamed (0.000000, 0.000000)

-- test_fromNameLatLong --
Brooklyn Center (45.076076, -93.332728)

Conclusions


Just a tiny bit of test code overpowered a large number of showstopper bugs!

Any of of the identified showstopper bugs would have rendered the unit code unusable.

Fixing these bugs gives us a much higher level of confidence that our code runs.

public void test_newInstance()  {
	prn("\n-- test_newInstance --");
	City city = City.newInstance();
	prn(city.toString());
}

public void test_fromNameLatLong()  {
	prn("\n-- test_fromNameLatLong --");
	City city =
		City.fromNameLatLong("Brooklyn Center", 45.076076, -93.332728);
	prn(city.toString());
}


Bug Summary


Bug Summary
1/16/2022

Unit: City.java
UnitTest: CityTest.java

===========================================================
Resolving Compiler Warnings (Unit)

-------------- Bug Notes --------------

The warning was that method param "nm" was not used
in method "MyCity(String nm, double lat, double lon)".
The fix was to set the ivar "name" with the param "nm"
(i.e., to use the param properly).


===========================================================
Bug Search via Compiler Errors (in Unit Test)

-------------- Bug Notes --------------

The UnitTest compiler error was that the package "model.geography"
could not be resolved.

The bug was that, the unit package was incorrectly
named "mygeography".

The bug-fix was to rename the unit pacakge
from "mygeography" to "geography".

-------------- Bug Notes --------------
	
The UnitTest compiler error was that "model.geography.City"
could not be resolved.

The bug was that the unit file name and class name
were both incorrectly named "MyCity".

The first bug-fix was to rename the file "MyCity.java" to "City.java".

The second bug-fix was to edit "City.java" and change all refs
from "MyCity" to "City".
	
-------------- Bug Notes --------------
	
The UnitTest compiler error was that
"model.geography.City" is not visible.

I determined that the bug was that, in the unit,
the class header was missing the access modifier "public".

The bug-fix was to add "public" to the class header:
	public class City
	

======================================================================
Bug Search via Running Unit Test

-------------- Bug Notes --------------

This was an interesting one.

When running the unit test, this exception occurred:
	A null pointer exception occurred
On this line (in the unit test):
	prn(city.toString());
I could infer that city must be null.
The previous code line is:
	City city = City.newInstance();
	prn(city.toString());
Therefore "City.newInstance()" must be returning null.

I investigated the unit and found that yes
indeed it was returning null (not good):

	return null;

The bug fix was to return the expected object:

	/** Returns new City object with name "Unnamed" and location (0, 0) */
	public static City newInstance() {
		//return null;
		return fromNameLatLong("Unnamed", 0, 0);
	}
	
-------------- Bug Notes --------------
	
Another fun one.

When running the unit test, this exception occurred:
	A null pointer exception occurred
On this line (in the unit):
	this.location.setLatitude(lat);
I could infer that the ivar "location" must be null.

Therefore, the ivar "location" must not have
been initialized.

The bug fix is to properly initialize the ivar before
using it:

was to return the expected object:

	this.location = GeoLocation.newInstance();
	this.location.setLatitude(lat);