class A {final B b;A(B b){ this.b = b;}}class B {final A a;B(){ this.a = new A(this);}}+---------+ +---------+| A |<-----| B | | | | | | |----->| |+---------+ +---------+
class A {final B b;A(B b){ this.b = b;}}class B {final A a;B(A a){ this.a = a;}}
+---------+ +---------+| A |<-----| B | | | | | +-+ | | | | +->|C| || |------+---->| | || | | +-+ |+---------+ +---------+
+---------++---------+ | B || A |<-------------| | | | | | | | +---+ | | | |--->| C |<----| | | | +---+ +---------+ +---------+ class C { C(){ } } class A { final C c; A(C c){ this.c = c; } } class B { final A a; final C c; B(A a, C c){ this.a = a; this.c = c; } }
public interface PlanetaryDeathRay { public void aim(double xPosition, double yPosition); public boolean fire(); /* call this if she says the rebel base is on Dantooine */}public class BlueLaserPlanetaryDeathRay implements PlanetaryDeathRay { /* implementation here */ }public class GreenLaserPlanetaryDeathRay implements PlanetaryDeathRay { /* implementation here */ }
public abstract class PlanetaryDeathRayTestCase extends TestCase { protected PlanetaryDeathRay deathRay; @Override protected void setUp() { deathRay = createDeathRay(); } @Override protected void tearDown() { deathRay = null; } protected abstract PlanetaryDeathRay createDeathRay(); /* create the PlanetaryDeathRay to test */ public void testAim() { /* write implementation-independent tests here against deathRay.aim() */ } public void testFire() { /* write implementation-independent tests here against deathRay.fire() */ }}
public class BlueLaserPlanetaryDeathRayTest extends PlanetaryDeathRayTestCase { protected PlanetaryDeathRay createDeathRay() { return new BlueLaserPlanetaryDeathRay(); }}
if
switch
instanceof
#ifdef PROD
class Mechanic { Engine engine; Mechanic(Context context) { this.engine = context.getEngine(); } }
class Mechanic { Engine engine; Mechanic(Engine engine) { this.engine = engine; } }
class Monitor { SparkPlug sparkPlug; Monitor(Context context) { this.sparkPlug = context. getCar().getEngine(). getPiston().getSparkPlug(); } }
Because the Google C++ Testing Framework was opensourced last week, there will be episodes focusing on it published here in the future. Watch for them. I've reshuffled the schedule to get one out this week.
Google C++ Testing Framework supports two families of assertions with the same interface:
As Moka the code monkey has shown Uni the testing robot, EXPECT is often more appropriate because it: reveals more failures in a single run, and allows more to be fixed in a single edit/compile/run-tests cycle. Example:
TEST(WordStemmerTest, StemsPluralSuffixes) { EXPECT_STREQ("jump", stemmer->Stem("jumps")); EXPECT_STREQ("pixi", stemmer->Stem("pixies")); EXPECT_STREQ("prioriti", stemmer->Stem("priorities")); // etc ...}
Use ASSERT when it doesn't make sense to continue. Example:
TEST(FileGeneratorTest, CreatesFileContainingSequenceOfChars) { ASSERT_TRUE(fp = fopen(path, "r")) << "Failed to open " << path; ASSERT_EQ(10, fread(buffer, 1, 10, fp)) << "File " << path << " is too small"; buffer[10] = '\0'; EXPECT_STREQ("123456789", buffer) << "File " << path << " is corrupted";}
Remember to download this episode of Testing on the Toilet and post it in your office.