Having trouble with a unit test and the Iterator interface

I recently got burned by a unit test that let a bad test case through. The software is still alpha so it isn’t floating out over the ether too badly, but any help with this would be appreciated. Here’s the test.


'Iterable' => function() use ( $obj, $params ) {
	try {
		$count = 0; // addint this to the test to insure we actually DO iterate!!
		foreach ($obj as $key => $val) {
			if (!isset($params[$key]) || $params[$key] != $val) {
				return UnitTest::FAIL;	
			}

			$count++;
		}
						
		if ($count != count($obj)) {
			return UnitTest::FAIL;
		}
						
		return UnitTest::PASSED;
	} catch ( \\Exception $e ) {
		return UnitTest::FAIL;
	}
},

Some explanation on what’s going on here. Unit tests in my framework exists as closures. $obj is the test class, $params are the parameters of the test. In this test $params is a normal array whose contents should be identical to the internal storage array of the object. The object implements Iterator. My original test did not keep a count of the number of loops in the foreach, so the test was defeated by the code skipping the foreach loop without error, and since there wasn’t a count check it returned a passed result.

And yes, I know of PHPUnit. For Gazelle I wanted a unit test library that could run on a default PHP install without a PECL library. This limits what the test framework can test, but Gazelle is being designed as a “learn from me” framework first and foremost, with production usability is a secondary concern (that doesn’t mean I want it to be unusable in production - I do, but that isn’t the framework’s main target). Gazelle’s unit tester can be used together with PHPUnit if one is so inclined.

Note - Countable is implemented on the object, and that functionality is tested before the test above runs. The way this test suite works is each test is a closure, and all tests are stored in an array of tests. The unit test manager iterates over the closures, runs each one, and gathers any fail reports they return then reports that whatever invoked it (tests can be ran from a browser page or from the command line unless they require services specific to those environments, like the $_SESSION superglobal).

But again, can anyone see any other reason why a non-iterable object could have gotten through this test and will my counting fix catch that?

Got to the bottom of the iterator problem, I wasn’t initializing the index element.