anchor.diff:    call(Project project, Iterable<Project> dependencies) {
       invocations.add(new TestProcessInvocation(project, dependencies));
     }
  +
  +  static createTests(
  +      TestProcessor processor(), List<TestProcessInvocation> expected) {
  +    test('has expected number of invocations', () {
  +      schedule(
  +          () => expect(processor().invocations, hasLength(expected.length)));
  +    });
  +
  +    group('each invocation matches expectation', () {
  +      for (int i = 0; i < expected.length; i++) {
  +        TestProcessInvocation.createTests(
  +            () => processor().invocations[i], expected[i]);
  +      }
  +    });
  +  }
   }
   
   class TestProcessInvocation {
  
positive.code: import 'package:mockito/mockito.dart';
  import 'package:devops/src/pubspec/pubspec.dart';
  import 'dart:async';
  
  main() {
    TestProcessor processor;
  
negative.code:   final Iterable<Project> dependencies;
  
    TestProcessInvocation(this.project, this.dependencies);
  
  //  bool operator==(other) => other is TestProcessInvocation
  //  && project == other.project && unorderedEquals();
  
  //  Matcher get matcher {
  //    new CustomMatcher()
  //  }
  
    static createTests(
        TestProcessInvocation actual(), TestProcessInvocation expected) {
      test('invocation has expected project', () {
        schedule(() => expect(actual().project, equals(expected.project)));
      });
  
      test('invocation has expected dependencies', () {
        schedule(() => expect(
            actual().dependencies, unorderedEquals(expected.dependencies)));
      });
    }
  }
  
  class MockProject extends Mock implements Project {
    MockProject(String name, PubSpec pubSpec) {
      when(this.name).thenReturn(name);
      when(this.pubspec).thenReturn(new Future.value(pubSpec));
    }
    noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
  }
  
  foo() {
    testCase(
        thatWhen: 'no projects provided',
        asProvidedBy: () => [],
        expectTheseInvocations: () => []);
  }
  
  testCase({String thatWhen, Iterable<Project> asProvidedBy(),
      List<TestProcessInvocation> expectTheseInvocations()}) {
    TestProcessor processor;
  
    scheduleForProjects(Iterable<Project> projects) {
      return schedule(() async {
        processor = new TestProcessor();
        final DependencyGraph graph = await getDependencyGraph(projects.toSet());
        return graph.depthFirst(processor);
      });
    }
  
    setUpForProjects(Iterable<Project> projects) {
      setUp(() => scheduleForProjects(projects));
    }
  
    group(thatWhen, () {
      setUpForProjects(asProvidedBy());
      TestProcessor.createTests(() => processor, expectTheseInvocations());
    });
  }
  
  awhen(String name, {Iterable<Project> withProjects()}) {}
  
  Project aproject(String name,
      {Iterable<PathReference> pathDependencies: const []}) {}
  
  class TestPrecondition {
    String description;
  //  String description;
  }
  