Add testsw
diff --git a/lib/src/process_pool.dart b/lib/src/process_pool.dart
index ada6658..59172a4 100644
--- a/lib/src/process_pool.dart
+++ b/lib/src/process_pool.dart
@@ -7,10 +7,13 @@
 import 'dart:io' show Directory, Platform, stdout, SystemEncoding, stderr, ProcessStartMode;
 
 import 'package:async/async.dart' show StreamGroup;
+import 'package:process_runner/process_runner.dart';
 
 import 'process_runner.dart';
 
 abstract class DependentJob {
+  DependentJob({Iterable<DependentJob> dependsOn = const <DependentJob>{}}) : _dependsOn = dependsOn.toSet();
+
   /// The name of the job.
   String get name;
 
@@ -19,11 +22,45 @@
   /// This job will not be scheduled until all of the jobs in this set have
   /// completed.
   ///
+  /// To add a dependency, call [addDependency] or [addDependencies].
+  ///
+  /// To remove a dependency, call [removeDependency] or [removeDependencies].
+  ///
+  /// Modifying the returned set will not affect the dependencies of this job.
+  ///
   /// Will throw if there is a dependency cycle, or if the given job has not
   /// been added to the pool.
   ///
   /// Defaults to an empty set.
-  Set<DependentJob> get dependsOn;
+  Set<DependentJob> get dependsOn => _dependsOn.toSet();
+  final Set<DependentJob> _dependsOn;
+
+  void addDependency(DependentJob job) {
+    if (job == this) {
+      throw ProcessRunnerException('A job cannot depend on itself');
+    }
+    if (_dependsOn.contains(job)) {
+      throw ProcessRunnerException('$job is already a dependency of $this');
+    }
+    if (job._dependsOn.contains(this)) {
+      throw ProcessRunnerException('$this is already a dependency of $job, no cycle allowed');
+    }
+    _dependsOn.add(job);
+  }
+
+  void removeDependency(DependentJob job) {
+    assert(_dependsOn.contains(job));
+    assert(job != this);
+    _dependsOn.remove(job);
+  }
+
+  void addDependencies(Iterable<DependentJob> jobs) {
+    jobs.forEach(addDependency);
+  }
+
+  void removeDependencies(Iterable<DependentJob> jobs) {
+    jobs.forEach(removeDependency);
+  }
 
   void addToQueue(List<DependentJob> jobs);
 }
@@ -44,7 +81,7 @@
     this.runInShell = false,
     Iterable<DependentJob>? dependsOn,
   })  : name = name ?? command.join(' '),
-        dependsOn = dependsOn?.toSet() ?? <DependentJob>{};
+        super(dependsOn: dependsOn?.toSet() ?? <DependentJob>{});
 
   /// The name of the job.
   ///
@@ -124,24 +161,18 @@
   }
 
   @override
-  Set<DependentJob> dependsOn;
-
-  @override
   String toString() => '${command.join(' ')} with ${dependsOn.length} dependencies';
 }
 
 class WorkerJobGroup extends DependentJob {
-  WorkerJobGroup(
-    this.workers, {
-    this.name = '<unknown>',
-    bool setDependencies = true,
-  })  : dependsOn = workers.toSet(),
-        assert(workers.isNotEmpty) {
-    // Make sure they run in series.
-    if (setDependencies) {
-      for (int i = 1; i < workers.length; i++) {
-        workers[i].dependsOn.add(workers[i - 1]);
-      }
+  WorkerJobGroup(Iterable<DependentJob> workers, {Iterable<DependentJob>? dependsOn, this.name = 'Group'})
+      : assert(workers.isNotEmpty),
+        workers = <DependentJob>[...workers],
+        super(dependsOn: <DependentJob>{...workers.toSet(), if (dependsOn != null) ...dependsOn}) {
+    // Make sure they run in series, and they depend on anything that the group
+    // depends on.
+    for (int i = 1; i < workers.length; i++) {
+      this.workers[i].addDependency(this.workers[i - 1]);
     }
   }
 
@@ -152,7 +183,20 @@
   final List<DependentJob> workers;
 
   @override
-  final Set<DependentJob> dependsOn;
+  void addDependency(DependentJob job) {
+    for (final DependentJob worker in workers) {
+      worker.addDependency(job);
+    }
+    super.addDependency(job);
+  }
+
+  @override
+  void removeDependency(DependentJob job) {
+    for (final DependentJob worker in workers) {
+      worker.removeDependency(job);
+    }
+    super.removeDependency(job);
+  }
 
   @override
   void addToQueue(List<DependentJob> jobs) {
diff --git a/test/src/process_pool_test.dart b/test/src/process_pool_test.dart
index 5bbf9f3..6a5903a 100644
--- a/test/src/process_pool_test.dart
+++ b/test/src/process_pool_test.dart
@@ -198,7 +198,7 @@
     };
     fakeProcessManager.fakeResults = calls;
     final WorkerJobGroup groupA = WorkerJobGroup(
-      <WorkerJob>[
+      <DependentJob>[
         WorkerJob(<String>['commandA1', 'arg1', 'arg2'], name: 'job A1'),
         WorkerJob(<String>['commandA2', 'arg1', 'arg2'], name: 'job A2'),
         WorkerJob(<String>['commandA3', 'arg1', 'arg2'], name: 'job A3'),
@@ -206,14 +206,14 @@
       name: 'Group A',
     );
     final WorkerJobGroup groupB = WorkerJobGroup(
-      <WorkerJob>[
+      <DependentJob>[
         WorkerJob(<String>['commandB1', 'arg1', 'arg2'], name: 'job B1'),
         WorkerJob(<String>['commandB2', 'arg1', 'arg2'], name: 'job B2'),
         WorkerJob(<String>['commandB3', 'arg1', 'arg2'], name: 'job B3'),
       ],
       name: 'Group B',
     );
-    groupB.dependsOn.add(groupA);
+    groupB.addDependency(groupA);
     final List<DependentJob> jobs = <DependentJob>[groupA, groupB];
     final List<WorkerJob> completed = await processPool.runToCompletion(jobs);
     expect(completed.length, equals(6));
@@ -233,19 +233,26 @@
       completed.where((WorkerJob job) => job.result.exitCode == 0).map((WorkerJob job) => job.name),
       unorderedEquals(<String>['job B1', 'job A1', 'job A2', 'job A3']),
     );
-    // Either group A or B can come first, but the individual group tasks should
-    // be in order.
-    expect(
-      <String>[completed[0].name, completed[1].name],
-      unorderedEquals(<String>['job A1', 'job B1']),
-    );
-    expect(
-      <String>[completed[2].name, completed[3].name],
-      unorderedEquals(<String>['job A2', 'job B2']),
-    );
-    expect(
-      <String>[completed[4].name, completed[5].name],
-      unorderedEquals(<String>['job A3', 'job B3']),
-    );
+  });
+test("Jobs can't depend on themselves", () async {
+    fakeProcessManager = FakeProcessManager((String value) {});
+    processRunner = ProcessRunner(processManager: fakeProcessManager);
+    processPool = ProcessPool(processRunner: processRunner, printReport: null);
+    final Map<FakeInvocationRecord, List<ProcessResult>> calls = <FakeInvocationRecord, List<ProcessResult>>{
+      FakeInvocationRecord(<String>['commandA1', 'arg1', 'arg2'], testPath): <ProcessResult>[
+        ProcessResult(0, 0, 'outputA1', 'stderrA1'),
+      ],
+    };
+    fakeProcessManager.fakeResults = calls;
+    final WorkerJob job = WorkerJob(<String>['commandA1', 'arg1', 'arg2'], name: 'job A1');
+
+    ProcessRunnerException? exception;
+    try {
+      job.addDependency(job);
+    } on ProcessRunnerException catch (e) {
+      exception = e;
+    }
+    expect(exception, isNotNull);
+    expect(exception!.message, equals('A job cannot depend on itself'));
   });
 }