Index: trunk/test/unit/org/openstreetmap/josm/data/validation/tests/CoastlinesTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/data/validation/tests/CoastlinesTest.java	(revision 10991)
+++ trunk/test/unit/org/openstreetmap/josm/data/validation/tests/CoastlinesTest.java	(revision 10991)
@@ -0,0 +1,38 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.validation.tests;
+
+import java.util.stream.Collectors;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+/**
+ * JUnit Test of coastline validation test.
+ */
+public class CoastlinesTest {
+
+    private static final Coastlines COASTLINES = new Coastlines();
+    private static final WronglyOrderedWays WRONGLY_ORDERED_WAYS = new WronglyOrderedWays();
+
+    /**
+     * Setup test.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().commands();
+
+    /**
+     * Test all error cases manually created in coastline.osm.
+     * @throws Exception in case of error
+     */
+    @Test
+    public void testCoastlineFile() throws Exception {
+        ValidatorTestUtils.testSampleFile("data_nodist/coastlines.osm",
+                ds -> ds.getWays().stream().filter(
+                        w -> "coastline".equals(w.get("natural"))).collect(Collectors.toList()),
+                null, COASTLINES, WRONGLY_ORDERED_WAYS);
+    }
+}
Index: trunk/test/unit/org/openstreetmap/josm/data/validation/tests/MultipolygonTestTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/data/validation/tests/MultipolygonTestTest.java	(revision 10989)
+++ trunk/test/unit/org/openstreetmap/josm/data/validation/tests/MultipolygonTestTest.java	(revision 10991)
@@ -5,13 +5,8 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
-import java.io.FileInputStream;
-import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
+import java.util.stream.Collectors;
 
 import org.junit.Rule;
@@ -22,8 +17,5 @@
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.validation.TestError;
-import org.openstreetmap.josm.gui.DefaultNameFormatter;
 import org.openstreetmap.josm.gui.mappaint.ElemStyles;
-import org.openstreetmap.josm.io.OsmReader;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
 
@@ -90,37 +82,7 @@
     @Test
     public void testMultipolygonFile() throws Exception {
-        try (InputStream is = new FileInputStream("data_nodist/multipolygon.osm")) {
-            for (Relation r : OsmReader.parseDataSet(is, null).getRelations()) {
-                if (r.isMultipolygon()) {
-                    String name = DefaultNameFormatter.getInstance().format(r);
-                    String codes = r.get("josm_error_codes");
-                    if (codes != null) {
-                        List<TestError> errors = new ArrayList<>();
-                        for (org.openstreetmap.josm.data.validation.Test test : Arrays.asList(MULTIPOLYGON_TEST, RELATION_TEST)) {
-                            test.initialize();
-                            test.startTest(null);
-                            test.visit(r);
-                            test.endTest();
-                            errors.addAll(test.getErrors());
-                        }
-                        Set<Integer> expectedCodes = new TreeSet<>();
-                        for (String code : codes.split(",")) {
-                            expectedCodes.add(Integer.parseInt(code));
-                        }
-                        Set<Integer> actualCodes = new TreeSet<>();
-                        for (TestError error : errors) {
-                            Integer code = error.getCode();
-                            assertTrue(name + " does not expect JOSM error code " + code + ": " + error.getDescription(),
-                                    expectedCodes.contains(code));
-                            actualCodes.add(code);
-                        }
-                        assertEquals(name + " " + expectedCodes + " => " + actualCodes,
-                                expectedCodes.size(), actualCodes.size());
-                    } else if (r.hasKey("name") && (r.getName().startsWith("06") || r.getName().startsWith("07"))) {
-                        fail(name + " lacks josm_error_codes tag");
-                    }
-                }
-            }
-        }
+        ValidatorTestUtils.testSampleFile("data_nodist/multipolygon.osm",
+                ds -> ds.getRelations().stream().filter(Relation::isMultipolygon).collect(Collectors.toList()),
+                name -> name.startsWith("06") || name.startsWith("07"), MULTIPOLYGON_TEST, RELATION_TEST);
     }
 }
Index: trunk/test/unit/org/openstreetmap/josm/data/validation/tests/ValidatorTestUtils.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/data/validation/tests/ValidatorTestUtils.java	(revision 10991)
+++ trunk/test/unit/org/openstreetmap/josm/data/validation/tests/ValidatorTestUtils.java	(revision 10991)
@@ -0,0 +1,71 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.validation.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.validation.Test;
+import org.openstreetmap.josm.data.validation.TestError;
+import org.openstreetmap.josm.gui.DefaultNameFormatter;
+import org.openstreetmap.josm.io.OsmReader;
+
+/**
+ * Utilities for validator unit tests.
+ */
+public final class ValidatorTestUtils {
+
+    private ValidatorTestUtils() {
+        // Hide default constructor for utilities classes
+    }
+
+    static <T extends OsmPrimitive> void testSampleFile(String sampleFile,
+            Function<DataSet, Iterable<T>> provider, Predicate<String> namePredicate,
+            Test ... tests) throws Exception {
+        try (InputStream is = new FileInputStream(sampleFile)) {
+            for (T t: provider.apply(OsmReader.parseDataSet(is, null))) {
+                String name = DefaultNameFormatter.getInstance().format(t);
+                String codes = t.get("josm_error_codes");
+                if (codes != null) {
+                    List<TestError> errors = new ArrayList<>();
+                    for (Test test : tests) {
+                        test.initialize();
+                        test.startTest(null);
+                        test.visit(Collections.singleton(t));
+                        test.endTest();
+                        errors.addAll(test.getErrors());
+                    }
+                    Set<Integer> expectedCodes = new TreeSet<>();
+                    if (!"none".equals(codes)) {
+                        for (String code : codes.split(",")) {
+                            expectedCodes.add(Integer.parseInt(code));
+                        }
+                    }
+                    Set<Integer> actualCodes = new TreeSet<>();
+                    for (TestError error : errors) {
+                        Integer code = error.getCode();
+                        assertTrue(name + " does not expect JOSM error code " + code + ": " + error.getDescription(),
+                                expectedCodes.contains(code));
+                        actualCodes.add(code);
+                    }
+                    assertEquals(name + " " + expectedCodes + " => " + actualCodes,
+                            expectedCodes.size(), actualCodes.size());
+                } else if (t.hasKey("name") && namePredicate != null && namePredicate.test(t.getName())) {
+                    fail(name + " lacks josm_error_codes tag");
+                }
+            }
+        }
+    }
+}
