Improve test coverage.
diff --git a/lib/tuple.dart b/lib/tuple.dart
index 5321f7c..bf874e1 100644
--- a/lib/tuple.dart
+++ b/lib/tuple.dart
@@ -22,6 +22,7 @@
 /// ```
 library tuple;
 
+import 'package:quiver/check.dart';
 import 'package:quiver/core.dart';
 
 /// Represents a 2-tuple, or pair.
@@ -37,10 +38,10 @@
 
   /// Create a new tuple value with the specified list [items].
   factory Tuple2.fromList(List items) {
-    if (items.length != 2) {
-      throw ArgumentError('items must have length 2');
-    }
-
+    checkArgument(
+      identical(items?.length, 2),
+      message: 'items must have two values',
+    );
     return Tuple2<T1, T2>(items[0] as T1, items[1] as T2);
   }
 
@@ -66,7 +67,7 @@
 
   @override
   bool operator ==(other) =>
-      other is Tuple2 && other.item1 == item1 && other.item2 == item2;
+      other is Tuple2<T1, T2> && other.item1 == item1 && other.item2 == item2;
 
   @override
   int get hashCode => hash2(item1.hashCode, item2.hashCode);
@@ -88,10 +89,8 @@
 
   /// Create a new tuple value with the specified list [items].
   factory Tuple3.fromList(List items) {
-    if (items.length != 3) {
-      throw ArgumentError('items must have length 3');
-    }
-
+    checkArgument(identical(items?.length, 3),
+        message: 'items must have three values');
     return Tuple3<T1, T2, T3>(items[0] as T1, items[1] as T2, items[2] as T3);
   }
 
@@ -122,7 +121,7 @@
 
   @override
   bool operator ==(other) =>
-      other is Tuple3 &&
+      other is Tuple3<T1, T2, T3> &&
       other.item1 == item1 &&
       other.item2 == item2 &&
       other.item3 == item3;
@@ -150,10 +149,8 @@
 
   /// Create a new tuple value with the specified list [items].
   factory Tuple4.fromList(List items) {
-    if (items.length != 4) {
-      throw ArgumentError('items must have length 4');
-    }
-
+    checkArgument(identical(items?.length, 4),
+        message: 'items must have four values');
     return Tuple4<T1, T2, T3, T4>(
         items[0] as T1, items[1] as T2, items[2] as T3, items[3] as T4);
   }
@@ -190,7 +187,7 @@
 
   @override
   bool operator ==(other) =>
-      other is Tuple4 &&
+      other is Tuple4<T1, T2, T3, T4> &&
       other.item1 == item1 &&
       other.item2 == item2 &&
       other.item3 == item3 &&
@@ -223,10 +220,10 @@
 
   /// Create a new tuple value with the specified list [items].
   factory Tuple5.fromList(List items) {
-    if (items.length != 5) {
-      throw ArgumentError('items must have length 5');
-    }
-
+    checkArgument(
+      identical(items?.length, 5),
+      message: 'items must have five values',
+    );
     return Tuple5<T1, T2, T3, T4, T5>(items[0] as T1, items[1] as T2,
         items[2] as T3, items[3] as T4, items[4] as T5);
   }
@@ -268,7 +265,7 @@
 
   @override
   bool operator ==(other) =>
-      other is Tuple5 &&
+      other is Tuple5<T1, T2, T3, T4, T5> &&
       other.item1 == item1 &&
       other.item2 == item2 &&
       other.item3 == item3 &&
@@ -311,10 +308,10 @@
 
   /// Create a new tuple value with the specified list [items].
   factory Tuple6.fromList(List items) {
-    if (items.length != 6) {
-      throw ArgumentError('items must have length 6');
-    }
-
+    checkArgument(
+      identical(items?.length, 6),
+      message: 'items must have six values',
+    );
     return Tuple6<T1, T2, T3, T4, T5, T6>(items[0] as T1, items[1] as T2,
         items[2] as T3, items[3] as T4, items[4] as T5, items[5] as T6);
   }
@@ -361,7 +358,7 @@
 
   @override
   bool operator ==(other) =>
-      other is Tuple6 &&
+      other is Tuple6<T1, T2, T3, T4, T5, T6> &&
       other.item1 == item1 &&
       other.item2 == item2 &&
       other.item3 == item3 &&
@@ -409,10 +406,10 @@
 
   /// Create a new tuple value with the specified list [items].
   factory Tuple7.fromList(List items) {
-    if (items.length != 7) {
-      throw ArgumentError('items must have length 7');
-    }
-
+    checkArgument(
+      identical(items?.length, 7),
+      message: 'items must have seven values',
+    );
     return Tuple7<T1, T2, T3, T4, T5, T6, T7>(
         items[0] as T1,
         items[1] as T2,
@@ -479,7 +476,7 @@
 
   @override
   bool operator ==(other) =>
-      other is Tuple7 &&
+      other is Tuple7<T1, T2, T3, T4, T5, T6, T7> &&
       other.item1 == item1 &&
       other.item2 == item2 &&
       other.item3 == item3 &&
diff --git a/test/tuple_test.dart b/test/tuple_test.dart
index 4f9a7ff..1eeb855 100644
--- a/test/tuple_test.dart
+++ b/test/tuple_test.dart
@@ -6,57 +6,1154 @@
 import 'package:tuple/tuple.dart';
 
 void main() {
-  final t = Tuple2<int, bool>(1, true);
+  group(Tuple2, () {
+    final t = Tuple2<int, String>(1, 'a');
 
-  test('items', () {
-    expect(t.item1, equals(1));
-    expect(t.item2, equals(true));
+    test('has the correct items', () {
+      expect(t.item1, 1);
+      expect(t.item2, 'a');
+    });
+
+    group('\'s fromList', () {
+      test('throws when items is null', () {
+        expect(() => Tuple2<int, String>.fromList(null), throwsArgumentError);
+      });
+
+      test('throws when items is empty', () {
+        expect(() => Tuple2<int, String>.fromList([]), throwsArgumentError);
+      });
+
+      test('throws when items has one value', () {
+        expect(() => Tuple2<int, String>.fromList([1]), throwsArgumentError);
+      });
+
+      test('throws when items has three values', () {
+        expect(() => Tuple2<int, String>.fromList([1, 'a', 3]),
+            throwsArgumentError);
+      });
+
+      test('throws when first value is not an int', () {
+        expect(
+            () => Tuple2<int, String>.fromList(['a', 'b']), throwsA(anything));
+      });
+
+      test('throws when second value is not a string', () {
+        expect(() => Tuple2<int, String>.fromList([1, 2.0]), throwsA(anything));
+      });
+    });
+
+    test('returns correct tuple from withItem1', () {
+      expect(t.withItem1(2), Tuple2<int, String>(2, 'a'));
+    });
+
+    test('returns correct tuple from withItem2', () {
+      expect(t.withItem2('b'), Tuple2<int, String>(1, 'b'));
+    });
+
+    group('\'s toList', () {
+      test('returns fixed list by default', () {
+        final list = t.toList();
+        expect(list, orderedEquals([1, 'a']));
+        expect(() => list.add(1), throwsA(TypeMatcher<UnsupportedError>()));
+      });
+
+      test('returns growable list when told so', () {
+        expect(
+            t.toList(growable: true)..add('b'), orderedEquals([1, 'a', 'b']));
+      });
+    });
+
+    test('converts to proper string', () {
+      expect('$t', '[1, a]');
+    });
+
+    test('does not equal null', () {
+      expect(t == null, isFalse);
+    });
+
+    test('does not equal when first value is different', () {
+      expect(t == t.withItem1(2), isFalse);
+    });
+
+    test('does not equal when second value is different', () {
+      expect(t == t.withItem2('b'), isFalse);
+    });
+
+    test('does not equal when both values are different', () {
+      expect(t == Tuple2<int, String>(2, 'b'), isFalse);
+    });
+
+    test('does not equal when first type is different', () {
+      expect(t == Tuple2<double, String>(1.0, 'a'), isFalse);
+    });
+
+    test('does not equal when second type is different', () {
+      expect(t == Tuple2<int, double>(1, 1.0), isFalse);
+    });
+
+    test('does not equal when both types are different', () {
+      expect(t == Tuple2<double, int>(1.0, 1), isFalse);
+    });
+
+    test('equals itself', () {
+      expect(t == t, isTrue);
+    });
+
+    test('equals another object with same values', () {
+      expect(t == Tuple2<int, String>(1, 'a'), isTrue);
+    });
+
+    test('can be used as a map key', () {
+      final map = <Tuple2<int, String>, int>{};
+      map[t] = 101;
+      expect(map[Tuple2<int, String>(1, 'a')], 101);
+    });
   });
 
-  test('withItems', () {
-    expect(t.withItem1(2), equals(Tuple2<int, bool>(2, true)));
-    expect(t.withItem2(false), equals(Tuple2<int, bool>(1, false)));
+  group(Tuple3, () {
+    final t = Tuple3<int, String, int>(1, 'a', 10);
+
+    test('has the correct items', () {
+      expect(t.item1, 1);
+      expect(t.item2, 'a');
+      expect(t.item3, 10);
+    });
+
+    group('\'s fromList', () {
+      test('throws when items is null', () {
+        expect(
+            () => Tuple3<int, String, int>.fromList(null), throwsArgumentError);
+      });
+
+      test('throws when items is empty', () {
+        expect(
+            () => Tuple3<int, String, int>.fromList([]), throwsArgumentError);
+      });
+
+      test('throws when items has one value', () {
+        expect(
+            () => Tuple3<int, String, int>.fromList([1]), throwsArgumentError);
+      });
+
+      test('throws when items has two values', () {
+        expect(() => Tuple3<int, String, int>.fromList([1, 'a']),
+            throwsArgumentError);
+      });
+
+      test('throws when items has four values', () {
+        expect(() => Tuple3<int, String, int>.fromList([1, 'a', 2, 3]),
+            throwsArgumentError);
+      });
+
+      test('throws when first value is not an int', () {
+        expect(() => Tuple3<int, String, int>.fromList(['', 'a', 10]),
+            throwsA(anything));
+      });
+
+      test('throws when second value is not a string', () {
+        expect(() => Tuple3<int, String, int>.fromList([1, 2, 10]),
+            throwsA(anything));
+      });
+
+      test('throws when third value is not an int', () {
+        expect(() => Tuple3<int, String, int>.fromList([1, 'a', 'b']),
+            throwsA(anything));
+      });
+    });
+
+    test('returns correct tuple from withItem1', () {
+      expect(t.withItem1(2), Tuple3<int, String, int>(2, 'a', 10));
+    });
+
+    test('returns correct tuple from withItem2', () {
+      expect(t.withItem2('b'), Tuple3<int, String, int>(1, 'b', 10));
+    });
+
+    test('returns correct tuple from withItem3', () {
+      expect(t.withItem3(100), Tuple3<int, String, int>(1, 'a', 100));
+    });
+
+    group('\'s toList', () {
+      test('returns fixed list by default', () {
+        final list = t.toList();
+        expect(list, orderedEquals([1, 'a', 10]));
+        expect(() => list.add(1), throwsA(TypeMatcher<UnsupportedError>()));
+      });
+
+      test('returns growable list when told so', () {
+        expect(t.toList(growable: true)..add('b'),
+            orderedEquals([1, 'a', 10, 'b']));
+      });
+    });
+
+    test('converts to proper string', () {
+      expect('$t', '[1, a, 10]');
+    });
+
+    test('does not equal null', () {
+      expect(t == null, isFalse);
+    });
+
+    test('does not equal when first value is different', () {
+      expect(t == t.withItem1(2), isFalse);
+    });
+
+    test('does not equal when second value is different', () {
+      expect(t == t.withItem2('b'), isFalse);
+    });
+
+    test('does not equal when third value is different', () {
+      expect(t == t.withItem3(100), isFalse);
+    });
+
+    test('does not equal when first type is different', () {
+      expect(t == Tuple3<double, String, int>(1.0, 'a', 10), isFalse);
+    });
+
+    test('does not equal when second type is different', () {
+      expect(t == Tuple3<int, double, int>(1, 1.0, 10), isFalse);
+    });
+
+    test('does not equal when third type is different', () {
+      expect(t == Tuple3<int, String, double>(1, 'a', 1.0), isFalse);
+    });
+
+    test('equals itself', () {
+      expect(t == t, isTrue);
+    });
+
+    test('equals another object with same values', () {
+      expect(t == Tuple3<int, String, int>(1, 'a', 10), isTrue);
+    });
+
+    test('can be used as a map key', () {
+      final map = <Tuple3<int, String, int>, int>{};
+      map[t] = 101;
+      expect(map[Tuple3<int, String, int>(1, 'a', 10)], 101);
+    });
   });
 
-  test('create a tuple from a list of items', () {
-    final t1 = Tuple2.fromList([1, true]);
-    expect(t1.item1, equals(1));
-    expect(t1.item2, equals(true));
+  group(Tuple4, () {
+    final t = Tuple4<int, String, int, String>(1, 'a', 10, 'b');
 
-    expect(() => Tuple2.fromList([1]), throwsA(TypeMatcher<ArgumentError>()));
-    expect(() => Tuple2.fromList([1, true, 'a']),
-        throwsA(TypeMatcher<ArgumentError>()));
+    test('has the correct items', () {
+      expect(t.item1, 1);
+      expect(t.item2, 'a');
+      expect(t.item3, 10);
+      expect(t.item4, 'b');
+    });
+
+    group('\'s fromList', () {
+      test('throws when items is null', () {
+        expect(() => Tuple4<int, String, int, String>.fromList(null),
+            throwsArgumentError);
+      });
+
+      test('throws when items is empty', () {
+        expect(() => Tuple4<int, String, int, String>.fromList([]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has one value', () {
+        expect(() => Tuple4<int, String, int, String>.fromList([1]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has two values', () {
+        expect(() => Tuple4<int, String, int, String>.fromList([1, 'a']),
+            throwsArgumentError);
+      });
+
+      test('throws when items has three values', () {
+        expect(() => Tuple4<int, String, int, String>.fromList([1, 'a', 2]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has five values', () {
+        expect(
+            () =>
+                Tuple4<int, String, int, String>.fromList([1, 'a', 2, 'b', 3]),
+            throwsArgumentError);
+      });
+
+      test('throws when first value is not an int', () {
+        expect(
+            () => Tuple4<int, String, int, String>.fromList(['', 'a', 2, 'b']),
+            throwsA(anything));
+      });
+
+      test('throws when second value is not a string', () {
+        expect(() => Tuple4<int, String, int, String>.fromList([1, 2, 3, 'b']),
+            throwsA(anything));
+      });
+
+      test('throws when third value is not an int', () {
+        expect(
+            () => Tuple4<int, String, int, String>.fromList([1, 'a', 'b', 2]),
+            throwsA(anything));
+      });
+
+      test('throws when fourth value is not a string', () {
+        expect(() => Tuple4<int, String, int, String>.fromList([1, 'a', 2, 3]),
+            throwsA(anything));
+      });
+    });
+
+    test('returns correct tuple from withItem1', () {
+      expect(t.withItem1(2), Tuple4<int, String, int, String>(2, 'a', 10, 'b'));
+    });
+
+    test('returns correct tuple from withItem2', () {
+      expect(
+          t.withItem2('b'), Tuple4<int, String, int, String>(1, 'b', 10, 'b'));
+    });
+
+    test('returns correct tuple from withItem3', () {
+      expect(
+          t.withItem3(100), Tuple4<int, String, int, String>(1, 'a', 100, 'b'));
+    });
+
+    test('returns correct tuple from withItem4', () {
+      expect(
+          t.withItem4('c'), Tuple4<int, String, int, String>(1, 'a', 10, 'c'));
+    });
+
+    group('\'s toList', () {
+      test('returns fixed list by default', () {
+        final list = t.toList();
+        expect(list, orderedEquals([1, 'a', 10, 'b']));
+        expect(() => list.add(1), throwsA(TypeMatcher<UnsupportedError>()));
+      });
+
+      test('returns growable list when told so', () {
+        expect(t.toList(growable: true)..add('c'),
+            orderedEquals([1, 'a', 10, 'b', 'c']));
+      });
+    });
+
+    test('converts to proper string', () {
+      expect('$t', '[1, a, 10, b]');
+    });
+
+    test('does not equal null', () {
+      expect(t == null, isFalse);
+    });
+
+    test('does not equal when first value is different', () {
+      expect(t == t.withItem1(2), isFalse);
+    });
+
+    test('does not equal when second value is different', () {
+      expect(t == t.withItem2('b'), isFalse);
+    });
+
+    test('does not equal when third value is different', () {
+      expect(t == t.withItem3(100), isFalse);
+    });
+
+    test('does not equal when fourth value is different', () {
+      expect(t == t.withItem4('c'), isFalse);
+    });
+
+    test('does not equal when first type is different', () {
+      expect(
+          t == Tuple4<double, String, int, String>(1.0, 'a', 10, 'b'), isFalse);
+    });
+
+    test('does not equal when second type is different', () {
+      expect(t == Tuple4<int, double, int, String>(1, 1.0, 10, 'b'), isFalse);
+    });
+
+    test('does not equal when third type is different', () {
+      expect(
+          t == Tuple4<int, String, double, String>(1, 'a', 1.0, 'b'), isFalse);
+    });
+
+    test('does not equal when fourth type is different', () {
+      expect(t == Tuple4<int, String, int, double>(1, 'a', 10, 1.0), isFalse);
+    });
+
+    test('equals itself', () {
+      expect(t == t, isTrue);
+    });
+
+    test('equals another object with same values', () {
+      expect(t == Tuple4<int, String, int, String>(1, 'a', 10, 'b'), isTrue);
+    });
+
+    test('can be used as a map key', () {
+      final map = <Tuple4<int, String, int, String>, int>{};
+      map[t] = 101;
+      expect(map[Tuple4<int, String, int, String>(1, 'a', 10, 'b')], 101);
+    });
   });
 
-  test('equality', () {
-    final otherT = Tuple2<int, bool>(1, true);
-    expect(t, equals(otherT));
+  group(Tuple5, () {
+    final t = Tuple5<int, String, int, String, int>(1, 'a', 10, 'b', 100);
+
+    test('has the correct items', () {
+      expect(t.item1, 1);
+      expect(t.item2, 'a');
+      expect(t.item3, 10);
+      expect(t.item4, 'b');
+      expect(t.item5, 100);
+    });
+
+    group('\'s fromList', () {
+      test('throws when items is null', () {
+        expect(() => Tuple5<int, String, int, String, int>.fromList(null),
+            throwsArgumentError);
+      });
+
+      test('throws when items is empty', () {
+        expect(() => Tuple5<int, String, int, String, int>.fromList([]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has one value', () {
+        expect(() => Tuple5<int, String, int, String, int>.fromList([1]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has two values', () {
+        expect(() => Tuple5<int, String, int, String, int>.fromList([1, 'a']),
+            throwsArgumentError);
+      });
+
+      test('throws when items has three values', () {
+        expect(
+            () => Tuple5<int, String, int, String, int>.fromList([1, 'a', 2]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has four values', () {
+        expect(
+            () => Tuple5<int, String, int, String, int>.fromList(
+                [1, 'a', 2, 'b']),
+            throwsArgumentError);
+      });
+
+      test('throws when items has six values', () {
+        expect(
+            () => Tuple5<int, String, int, String, int>.fromList(
+                [1, 'a', 2, 'b', 3, 'c']),
+            throwsArgumentError);
+      });
+
+      test('throws when first value is not an int', () {
+        expect(
+            () => Tuple5<int, String, int, String, int>.fromList(
+                ['z', 'a', 2, 'b', 3]),
+            throwsA(anything));
+      });
+
+      test('throws when second value is not a string', () {
+        expect(
+            () => Tuple5<int, String, int, String, int>.fromList(
+                [1, 0, 2, 'b', 3]),
+            throwsA(anything));
+      });
+
+      test('throws when third value is not an int', () {
+        expect(
+            () => Tuple5<int, String, int, String, int>.fromList(
+                [1, 'a', 'z', 'b', 3]),
+            throwsA(anything));
+      });
+
+      test('throws when fourth value is not a string', () {
+        expect(
+            () => Tuple5<int, String, int, String, int>.fromList(
+                [1, 'a', 2, 0, 3]),
+            throwsA(anything));
+      });
+
+      test('throws when fifth value is not an int', () {
+        expect(
+            () => Tuple5<int, String, int, String, int>.fromList(
+                [1, 'a', 2, 'b', 'z']),
+            throwsA(anything));
+      });
+    });
+
+    test('returns correct tuple from withItem1', () {
+      expect(t.withItem1(2),
+          Tuple5<int, String, int, String, int>(2, 'a', 10, 'b', 100));
+    });
+
+    test('returns correct tuple from withItem2', () {
+      expect(t.withItem2('b'),
+          Tuple5<int, String, int, String, int>(1, 'b', 10, 'b', 100));
+    });
+
+    test('returns correct tuple from withItem3', () {
+      expect(t.withItem3(100),
+          Tuple5<int, String, int, String, int>(1, 'a', 100, 'b', 100));
+    });
+
+    test('returns correct tuple from withItem4', () {
+      expect(t.withItem4('c'),
+          Tuple5<int, String, int, String, int>(1, 'a', 10, 'c', 100));
+    });
+
+    test('returns correct tuple from withItem5', () {
+      expect(t.withItem5(4),
+          Tuple5<int, String, int, String, int>(1, 'a', 10, 'b', 4));
+    });
+
+    group('\'s toList', () {
+      test('returns fixed list by default', () {
+        final list = t.toList();
+        expect(list, orderedEquals([1, 'a', 10, 'b', 100]));
+        expect(() => list.add(1), throwsA(TypeMatcher<UnsupportedError>()));
+      });
+
+      test('returns growable list when told so', () {
+        expect(t.toList(growable: true)..add('c'),
+            orderedEquals([1, 'a', 10, 'b', 100, 'c']));
+      });
+    });
+
+    test('converts to proper string', () {
+      expect('$t', '[1, a, 10, b, 100]');
+    });
+
+    test('does not equal null', () {
+      expect(t == null, isFalse);
+    });
+
+    test('does not equal when first value is different', () {
+      expect(t == t.withItem1(2), isFalse);
+    });
+
+    test('does not equal when second value is different', () {
+      expect(t == t.withItem2('b'), isFalse);
+    });
+
+    test('does not equal when third value is different', () {
+      expect(t == t.withItem3(100), isFalse);
+    });
+
+    test('does not equal when fourth value is different', () {
+      expect(t == t.withItem4('c'), isFalse);
+    });
+
+    test('does not equal when fifth value is different', () {
+      expect(t == t.withItem5(0), isFalse);
+    });
+
+    test('does not equal when first type is different', () {
+      expect(
+          t == Tuple5<double, String, int, String, int>(1.0, 'a', 10, 'b', 100),
+          isFalse);
+    });
+
+    test('does not equal when second type is different', () {
+      expect(t == Tuple5<int, double, int, String, int>(1, 1.0, 10, 'b', 100),
+          isFalse);
+    });
+
+    test('does not equal when third type is different', () {
+      expect(
+          t == Tuple5<int, String, double, String, int>(1, 'a', 1.0, 'b', 100),
+          isFalse);
+    });
+
+    test('does not equal when fourth type is different', () {
+      expect(t == Tuple5<int, String, int, double, int>(1, 'a', 10, 1.0, 100),
+          isFalse);
+    });
+
+    test('does not equal when fifth type is different', () {
+      expect(
+          t == Tuple5<int, String, int, String, double>(1, 'a', 10, 'b', 1.0),
+          isFalse);
+    });
+
+    test('equals itself', () {
+      expect(t == t, isTrue);
+    });
+
+    test('equals another object with same values', () {
+      expect(t == Tuple5<int, String, int, String, int>(1, 'a', 10, 'b', 100),
+          isTrue);
+    });
+
+    test('can be used as a map key', () {
+      final map = <Tuple5<int, String, int, String, int>, int>{};
+      map[t] = 101;
+      expect(map[Tuple5<int, String, int, String, int>(1, 'a', 10, 'b', 100)],
+          101);
+    });
   });
 
-  test('nested equality', () {
-    final t1 =
-        Tuple2<Tuple2<int, String>, bool>(Tuple2<int, String>(3, 'a'), false);
-    final t2 =
-        Tuple2<Tuple2<int, String>, bool>(Tuple2<int, String>(3, 'a'), false);
-    expect(t1, equals(t2));
+  group(Tuple6, () {
+    final t = Tuple6<int, String, int, String, int, String>(
+        1, 'a', 10, 'b', 100, 'c');
+
+    test('has the correct items', () {
+      expect(t.item1, 1);
+      expect(t.item2, 'a');
+      expect(t.item3, 10);
+      expect(t.item4, 'b');
+      expect(t.item5, 100);
+      expect(t.item6, 'c');
+    });
+
+    group('\'s fromList', () {
+      test('throws when items is null', () {
+        expect(
+            () => Tuple6<int, String, int, String, int, String>.fromList(null),
+            throwsArgumentError);
+      });
+
+      test('throws when items is empty', () {
+        expect(() => Tuple6<int, String, int, String, int, String>.fromList([]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has one value', () {
+        expect(
+            () => Tuple6<int, String, int, String, int, String>.fromList([1]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has two values', () {
+        expect(
+            () => Tuple6<int, String, int, String, int, String>.fromList(
+                [1, 'a']),
+            throwsArgumentError);
+      });
+
+      test('throws when items has three values', () {
+        expect(
+            () => Tuple6<int, String, int, String, int, String>.fromList(
+                [1, 'a', 2]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has four values', () {
+        expect(
+            () => Tuple6<int, String, int, String, int, String>.fromList(
+                [1, 'a', 2, 'b']),
+            throwsArgumentError);
+      });
+
+      test('throws when items has five values', () {
+        expect(
+            () => Tuple6<int, String, int, String, int, String>.fromList(
+                [1, 'a', 2, 'b', 3]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has seven values', () {
+        expect(
+            () => Tuple6<int, String, int, String, int, String>.fromList(
+                [1, 'a', 2, 'b', 3, 'c', 4]),
+            throwsArgumentError);
+      });
+
+      test('throws when first value is not an int', () {
+        expect(
+            () => Tuple6<int, String, int, String, int, String>.fromList(
+                ['z', 'a', 2, 'b', 3, 'c']),
+            throwsA(anything));
+      });
+
+      test('throws when second value is not a string', () {
+        expect(
+            () => Tuple6<int, String, int, String, int, String>.fromList(
+                [1, 0, 2, 'b', 3, 'c']),
+            throwsA(anything));
+      });
+
+      test('throws when third value is not an int', () {
+        expect(
+            () => Tuple6<int, String, int, String, int, String>.fromList(
+                [1, 'a', 'z', 'b', 3, 'c']),
+            throwsA(anything));
+      });
+
+      test('throws when fourth value is not a string', () {
+        expect(
+            () => Tuple6<int, String, int, String, int, String>.fromList(
+                [1, 'a', 2, 0, 3, 'c']),
+            throwsA(anything));
+      });
+
+      test('throws when fifth value is not an int', () {
+        expect(
+            () => Tuple6<int, String, int, String, int, String>.fromList(
+                [1, 'a', 2, 'b', 'z', 'c']),
+            throwsA(anything));
+      });
+
+      test('throws when sixth value is not a string', () {
+        expect(
+            () => Tuple6<int, String, int, String, int, String>.fromList(
+                [1, 'a', 2, 'b', 3, 4]),
+            throwsA(anything));
+      });
+    });
+
+    test('returns correct tuple from withItem1', () {
+      expect(
+          t.withItem1(2),
+          Tuple6<int, String, int, String, int, String>(
+              2, 'a', 10, 'b', 100, 'c'));
+    });
+
+    test('returns correct tuple from withItem2', () {
+      expect(
+          t.withItem2('b'),
+          Tuple6<int, String, int, String, int, String>(
+              1, 'b', 10, 'b', 100, 'c'));
+    });
+
+    test('returns correct tuple from withItem3', () {
+      expect(
+          t.withItem3(100),
+          Tuple6<int, String, int, String, int, String>(
+              1, 'a', 100, 'b', 100, 'c'));
+    });
+
+    test('returns correct tuple from withItem4', () {
+      expect(
+          t.withItem4('c'),
+          Tuple6<int, String, int, String, int, String>(
+              1, 'a', 10, 'c', 100, 'c'));
+    });
+
+    test('returns correct tuple from withItem5', () {
+      expect(
+          t.withItem5(4),
+          Tuple6<int, String, int, String, int, String>(
+              1, 'a', 10, 'b', 4, 'c'));
+    });
+
+    test('returns correct tuple from withItem6', () {
+      expect(
+          t.withItem6('z'),
+          Tuple6<int, String, int, String, int, String>(
+              1, 'a', 10, 'b', 100, 'z'));
+    });
+
+    group('\'s toList', () {
+      test('returns fixed list by default', () {
+        final list = t.toList();
+        expect(list, orderedEquals([1, 'a', 10, 'b', 100, 'c']));
+        expect(() => list.add(1), throwsA(TypeMatcher<UnsupportedError>()));
+      });
+
+      test('returns growable list when told so', () {
+        expect(t.toList(growable: true)..add(1),
+            orderedEquals([1, 'a', 10, 'b', 100, 'c', 1]));
+      });
+    });
+
+    test('converts to proper string', () {
+      expect('$t', '[1, a, 10, b, 100, c]');
+    });
+
+    test('does not equal null', () {
+      expect(t == null, isFalse);
+    });
+
+    test('does not equal when first value is different', () {
+      expect(t == t.withItem1(2), isFalse);
+    });
+
+    test('does not equal when second value is different', () {
+      expect(t == t.withItem2('b'), isFalse);
+    });
+
+    test('does not equal when third value is different', () {
+      expect(t == t.withItem3(100), isFalse);
+    });
+
+    test('does not equal when fourth value is different', () {
+      expect(t == t.withItem4('c'), isFalse);
+    });
+
+    test('does not equal when fifth value is different', () {
+      expect(t == t.withItem5(0), isFalse);
+    });
+
+    test('does not equal when sixth value is different', () {
+      expect(t == t.withItem6('z'), isFalse);
+    });
+
+    test('does not equal when first type is different', () {
+      expect(
+          t ==
+              Tuple6<double, String, int, String, int, String>(
+                  1.0, 'a', 10, 'b', 100, 'c'),
+          isFalse);
+    });
+
+    test('does not equal when second type is different', () {
+      expect(
+          t ==
+              Tuple6<int, double, int, String, int, String>(
+                  1, 1.0, 10, 'b', 100, 'c'),
+          isFalse);
+    });
+
+    test('does not equal when third type is different', () {
+      expect(
+          t ==
+              Tuple6<int, String, double, String, int, String>(
+                  1, 'a', 1.0, 'b', 100, 'c'),
+          isFalse);
+    });
+
+    test('does not equal when fourth type is different', () {
+      expect(
+          t ==
+              Tuple6<int, String, int, double, int, String>(
+                  1, 'a', 10, 1.0, 100, 'c'),
+          isFalse);
+    });
+
+    test('does not equal when fifth type is different', () {
+      expect(
+          t ==
+              Tuple6<int, String, int, String, double, String>(
+                  1, 'a', 10, 'b', 1.0, 'c'),
+          isFalse);
+    });
+
+    test('does not equal when sixth type is different', () {
+      expect(
+          t ==
+              Tuple6<int, String, int, String, int, double>(
+                  1, 'a', 10, 'b', 100, 0),
+          isFalse);
+    });
+
+    test('equals itself', () {
+      expect(t == t, isTrue);
+    });
+
+    test('equals another object with same values', () {
+      expect(
+          t ==
+              Tuple6<int, String, int, String, int, String>(
+                  1, 'a', 10, 'b', 100, 'c'),
+          isTrue);
+    });
+
+    test('can be used as a map key', () {
+      final map = <Tuple6<int, String, int, String, int, String>, int>{};
+      map[t] = 101;
+      expect(
+          map[Tuple6<int, String, int, String, int, String>(
+              1, 'a', 10, 'b', 100, 'c')],
+          101);
+    });
   });
 
-  test('can be used as keys in maps', () {
-    final map = {t: 'a'};
-    final key = Tuple2<int, bool>(1, true);
-    expect(map[key], equals('a'));
-  });
+  group(Tuple7, () {
+    final t = Tuple7<int, String, int, String, int, String, int>(
+        1, 'a', 10, 'b', 100, 'c', 1000);
 
-  test('toList() should return a listing containing the items of the tuple',
-      () {
-    expect(t.toList(), orderedEquals([1, true]));
-  });
+    test('has the correct items', () {
+      expect(t.item1, 1);
+      expect(t.item2, 'a');
+      expect(t.item3, 10);
+      expect(t.item4, 'b');
+      expect(t.item5, 100);
+      expect(t.item6, 'c');
+      expect(t.item7, 1000);
+    });
 
-  test('toList() should return a fixed list by default', () {
-    expect(() => t.toList().add(3), throwsA(TypeMatcher<UnsupportedError>()));
-  });
+    group('\'s fromList', () {
+      test('throws when items is null', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                null),
+            throwsArgumentError);
+      });
 
-  test('toList(growable: true) should return a growable list', () {
-    expect(t.toList(growable: true)..add('a'), orderedEquals([1, true, 'a']));
+      test('throws when items is empty', () {
+        expect(
+            () =>
+                Tuple7<int, String, int, String, int, String, int>.fromList([]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has one value', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                [1]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has two values', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                [1, 'a']),
+            throwsArgumentError);
+      });
+
+      test('throws when items has three values', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                [1, 'a', 2]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has four values', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                [1, 'a', 2, 'b']),
+            throwsArgumentError);
+      });
+
+      test('throws when items has five values', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                [1, 'a', 2, 'b', 3]),
+            throwsArgumentError);
+      });
+
+      test('throws when items has six values', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                [1, 'a', 2, 'b', 3, 'c']),
+            throwsArgumentError);
+      });
+
+      test('throws when items has eight values', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                [1, 'a', 2, 'b', 3, 'c', 4, 'd']),
+            throwsArgumentError);
+      });
+
+      test('throws when first value is not an int', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                ['z', 'a', 2, 'b', 3, 'c', 4]),
+            throwsA(anything));
+      });
+
+      test('throws when second value is not a string', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                [1, 0, 2, 'b', 3, 'c', 4]),
+            throwsA(anything));
+      });
+
+      test('throws when third value is not an int', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                [1, 'a', 'z', 'b', 3, 'c', 4]),
+            throwsA(anything));
+      });
+
+      test('throws when fourth value is not a string', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                [1, 'a', 2, 0, 3, 'c', 4]),
+            throwsA(anything));
+      });
+
+      test('throws when fifth value is not an int', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                [1, 'a', 2, 'b', 'z', 'c', 4]),
+            throwsA(anything));
+      });
+
+      test('throws when sixth value is not a string', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                [1, 'a', 2, 'b', 3, 4, 5]),
+            throwsA(anything));
+      });
+
+      test('throws when seventh value is not an int', () {
+        expect(
+            () => Tuple7<int, String, int, String, int, String, int>.fromList(
+                [1, 'a', 2, 'b', 3, 'c', 'd']),
+            throwsA(anything));
+      });
+    });
+
+    test('returns correct tuple from withItem1', () {
+      expect(
+          t.withItem1(2),
+          Tuple7<int, String, int, String, int, String, int>(
+              2, 'a', 10, 'b', 100, 'c', 1000));
+    });
+
+    test('returns correct tuple from withItem2', () {
+      expect(
+          t.withItem2('b'),
+          Tuple7<int, String, int, String, int, String, int>(
+              1, 'b', 10, 'b', 100, 'c', 1000));
+    });
+
+    test('returns correct tuple from withItem3', () {
+      expect(
+          t.withItem3(100),
+          Tuple7<int, String, int, String, int, String, int>(
+              1, 'a', 100, 'b', 100, 'c', 1000));
+    });
+
+    test('returns correct tuple from withItem4', () {
+      expect(
+          t.withItem4('c'),
+          Tuple7<int, String, int, String, int, String, int>(
+              1, 'a', 10, 'c', 100, 'c', 1000));
+    });
+
+    test('returns correct tuple from withItem5', () {
+      expect(
+          t.withItem5(4),
+          Tuple7<int, String, int, String, int, String, int>(
+              1, 'a', 10, 'b', 4, 'c', 1000));
+    });
+
+    test('returns correct tuple from withItem6', () {
+      expect(
+          t.withItem6('z'),
+          Tuple7<int, String, int, String, int, String, int>(
+              1, 'a', 10, 'b', 100, 'z', 1000));
+    });
+
+    test('returns correct tuple from withItem7', () {
+      expect(
+          t.withItem7(0),
+          Tuple7<int, String, int, String, int, String, int>(
+              1, 'a', 10, 'b', 100, 'c', 0));
+    });
+
+    group('\'s toList', () {
+      test('returns fixed list by default', () {
+        final list = t.toList();
+        expect(list, orderedEquals([1, 'a', 10, 'b', 100, 'c', 1000]));
+        expect(() => list.add(1), throwsA(TypeMatcher<UnsupportedError>()));
+      });
+
+      test('returns growable list when told so', () {
+        expect(t.toList(growable: true)..add(1),
+            orderedEquals([1, 'a', 10, 'b', 100, 'c', 1000, 1]));
+      });
+    });
+
+    test('converts to proper string', () {
+      expect('$t', '[1, a, 10, b, 100, c, 1000]');
+    });
+
+    test('does not equal null', () {
+      expect(t == null, isFalse);
+    });
+
+    test('does not equal when first value is different', () {
+      expect(t == t.withItem1(2), isFalse);
+    });
+
+    test('does not equal when second value is different', () {
+      expect(t == t.withItem2('b'), isFalse);
+    });
+
+    test('does not equal when third value is different', () {
+      expect(t == t.withItem3(100), isFalse);
+    });
+
+    test('does not equal when fourth value is different', () {
+      expect(t == t.withItem4('c'), isFalse);
+    });
+
+    test('does not equal when fifth value is different', () {
+      expect(t == t.withItem5(0), isFalse);
+    });
+
+    test('does not equal when sixth value is different', () {
+      expect(t == t.withItem6('z'), isFalse);
+    });
+
+    test('does not equal when seventh value is different', () {
+      expect(t == t.withItem7(0), isFalse);
+    });
+
+    test('does not equal when first type is different', () {
+      expect(
+          t ==
+              Tuple7<double, String, int, String, int, String, int>(
+                  1.0, 'a', 10, 'b', 100, 'c', 1000),
+          isFalse);
+    });
+
+    test('does not equal when second type is different', () {
+      expect(
+          t ==
+              Tuple7<int, double, int, String, int, String, int>(
+                  1, 1.0, 10, 'b', 100, 'c', 1000),
+          isFalse);
+    });
+
+    test('does not equal when third type is different', () {
+      expect(
+          t ==
+              Tuple7<int, String, double, String, int, String, int>(
+                  1, 'a', 1.0, 'b', 100, 'c', 1000),
+          isFalse);
+    });
+
+    test('does not equal when fourth type is different', () {
+      expect(
+          t ==
+              Tuple7<int, String, int, double, int, String, int>(
+                  1, 'a', 10, 1.0, 100, 'c', 1000),
+          isFalse);
+    });
+
+    test('does not equal when fifth type is different', () {
+      expect(
+          t ==
+              Tuple7<int, String, int, String, double, String, int>(
+                  1, 'a', 10, 'b', 1.0, 'c', 1000),
+          isFalse);
+    });
+
+    test('does not equal when sixth type is different', () {
+      expect(
+          t ==
+              Tuple7<int, String, int, String, int, double, int>(
+                  1, 'a', 10, 'b', 100, 0.0, 0),
+          isFalse);
+    });
+
+    test('does not equal when sixth type is different', () {
+      expect(
+          t ==
+              Tuple7<int, String, int, String, int, String, double>(
+                  1, 'a', 10, 'b', 100, 'c', 0.0),
+          isFalse);
+    });
+
+    test('equals itself', () {
+      expect(t == t, isTrue);
+    });
+
+    test('equals another object with same values', () {
+      expect(
+          t ==
+              Tuple7<int, String, int, String, int, String, int>(
+                  1, 'a', 10, 'b', 100, 'c', 1000),
+          isTrue);
+    });
+
+    test('can be used as a map key', () {
+      final map = <Tuple7<int, String, int, String, int, String, int>, int>{};
+      map[t] = 101;
+      expect(
+          map[Tuple7<int, String, int, String, int, String, int>(
+              1, 'a', 10, 'b', 100, 'c', 1000)],
+          101);
+    });
   });
 }