curl/tdd/runner is a bit complicated atm. Just thinking of something that might be a bit simpler:
curl(['curl/tdd/isolate'], function (isolate) {
	// inject AMD `require` and `define`, as well as a "done" callback.
	// the test function is guaranteed to run in isolation and all modules 
	// are undefined afterward.
	isolate(function test (require, define, done) {
		// define mocks:
		define('pkg/mod1', { foo: 42 });
		define('pkg/mod2', ['pkg/dep1'], function (dep1) {
			return {
				bar: function (val) { return String(dep1(val)); }
			}
		});
		// fetch the module to test and any unmocked modules
		require(['pkg/unit/to/test'], function (unitToTest) {
			// tests go here
			assert.equals('a string', unitToTest.method('a string'));
			unitToTest.asyncThing(function (val) {
				// more tests
				assert.true(val);
				done();
			})
		});
		// hmmm. anything here will exec before require callback and may
		// cause confusion?
	});
});Here's another possible API that removes the uncertainty of code around the async require:
curl(['curl/tdd/isolate'], function (isolate) {
	// the test function is run in isolation and the mocker function is run
	// immediately prior.  all modules are undefined afterward.
	isolate(
		['pkg/unit/to/test', 'other/unmocked/thing'],
		function mocker (define) {
			// define mocks:
			define('pkg/mod1', { foo: 42 });
			define('pkg/mod2', ['pkg/dep1'], function (dep1) {
				return {
					bar: function (val) { return String(dep1(val)); }
				}
			});
		},
		function test (unitToTest, otherThing, /* yuk: extra param */ done) {
			// tests go here
			assert.equals('a string', unitToTest.method('a string'));
			unitToTest.asyncThing(function (val) {
				assert.true(val);
				done();
			})
		}
	);
});It should be pretty easy to make it configurable:
// example config to use curl/tdd/isolate with requirejs
isolate.config({
	require: requirejs,
	define: define, // redundant
	undefine: requirejs.undefine
});// setup and teardown ???
isolate.config({
	setup: mySetupFunction, // runs before each mocker function
	teardown: myteardownFunction // runs after each test
});Since js is single-threaded, we could obtain a done function inside the test:
function test (unitToTest, otherThing) {
	var done = isolate.waitFor('my test'); // get a named "done" function
	// tests go here
	assert.equals('a string', unitToTest.method('a string'));
	unitToTest.asyncThing(function (val) {
		assert.true(val);
		done();
	})
}
I like the look of the commonjs-style sync require() version. I think I could still get that to work with other AMD loaders, too. Behind the scenes, it'd have to do something like this to invoke the "AMD-wrapped CommonJS" rules in a cross-loader way:
define('some-unique-name' + counter++, isolatedTestFunc);