Index: trunk/test/unit/org/openstreetmap/josm/TestUtils.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/TestUtils.java	(revision 14099)
+++ trunk/test/unit/org/openstreetmap/josm/TestUtils.java	(revision 14100)
@@ -26,4 +26,5 @@
 import java.util.Comparator;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ThreadPoolExecutor;
@@ -50,4 +51,5 @@
 import org.openstreetmap.josm.tools.JosmRuntimeException;
 import org.openstreetmap.josm.tools.Utils;
+import org.reflections.Reflections;
 
 import com.github.tomakehurst.wiremock.WireMockServer;
@@ -516,3 +518,13 @@
         }
     }
+
+    /**
+     * Returns all JOSM subtypes of the given class.
+     * @param <T> class
+     * @param superClass class
+     * @return all JOSM subtypes of the given class
+     */
+    public static <T> Set<Class<? extends T>> getJosmSubtypes(Class<T> superClass) {
+        return new Reflections("org.openstreetmap.josm").getSubTypesOf(superClass);
+    }
 }
Index: trunk/test/unit/org/openstreetmap/josm/data/osm/search/SearchCompilerTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/data/osm/search/SearchCompilerTest.java	(revision 14099)
+++ trunk/test/unit/org/openstreetmap/josm/data/osm/search/SearchCompilerTest.java	(revision 14100)
@@ -14,5 +14,7 @@
 import java.util.Collection;
 import java.util.Collections;
-
+import java.util.Set;
+
+import org.junit.Assert;
 import org.junit.Rule;
 import org.junit.Test;
@@ -39,7 +41,10 @@
 import org.openstreetmap.josm.gui.tagging.presets.items.Key;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.date.DateUtils;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import nl.jqno.equalsverifier.EqualsVerifier;
+import nl.jqno.equalsverifier.Warning;
 
 /**
@@ -701,3 +706,26 @@
         }
     }
+
+    /**
+     * Unit test of methods {@link Match#equals} and {@link Match#hashCode}, including all subclasses.
+     */
+    @Test
+    public void testEqualsContract() {
+        TestUtils.assumeWorkingEqualsVerifier();
+        Set<Class<? extends Match>> matchers = TestUtils.getJosmSubtypes(Match.class);
+        Assert.assertTrue(matchers.size() >= 10); // if it finds less than 10 classes, something is broken
+        for (Class<?> c : matchers) {
+            Logging.debug(c.toString());
+            EqualsVerifier.forClass(c).usingGetClass()
+                .suppress(Warning.NONFINAL_FIELDS, Warning.INHERITED_DIRECTLY_FROM_OBJECT)
+                .withPrefabValues(TaggingPreset.class, newTaggingPreset("foo"), newTaggingPreset("bar"))
+                .verify();
+        }
+    }
+
+    private static TaggingPreset newTaggingPreset(String name) {
+        TaggingPreset result = new TaggingPreset();
+        result.name = name;
+        return result;
+    }
 }
Index: trunk/test/unit/org/openstreetmap/josm/gui/TableCellRendererTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/gui/TableCellRendererTest.java	(revision 14099)
+++ trunk/test/unit/org/openstreetmap/josm/gui/TableCellRendererTest.java	(revision 14100)
@@ -16,7 +16,7 @@
 import org.junit.Rule;
 import org.junit.Test;
+import org.openstreetmap.josm.TestUtils;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
 import org.openstreetmap.josm.tools.Utils;
-import org.reflections.Reflections;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -61,6 +61,5 @@
     @Test
     public void testTableCellRenderer() throws ReflectiveOperationException {
-        Reflections reflections = new Reflections("org.openstreetmap.josm");
-        Set<Class<? extends TableCellRenderer>> renderers = reflections.getSubTypesOf(TableCellRenderer.class);
+        Set<Class<? extends TableCellRenderer>> renderers = TestUtils.getJosmSubtypes(TableCellRenderer.class);
         Assert.assertTrue(renderers.size() >= 10); // if it finds less than 10 classes, something is broken
         JTable tbl = new JTable(2, 2);
Index: trunk/test/unit/org/openstreetmap/josm/tools/template_engine/TemplateEntryTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/tools/template_engine/TemplateEntryTest.java	(revision 14100)
+++ trunk/test/unit/org/openstreetmap/josm/tools/template_engine/TemplateEntryTest.java	(revision 14100)
@@ -0,0 +1,44 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.tools.template_engine;
+
+import java.util.Set;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.TestUtils;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.tools.Logging;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import nl.jqno.equalsverifier.EqualsVerifier;
+import nl.jqno.equalsverifier.Warning;
+
+/**
+ * Unit tests of {@link TemplateEntry} class.
+ */
+public class TemplateEntryTest {
+
+    /**
+     * Setup rule.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules();
+
+    /**
+     * Unit test of methods {@link TemplateEntry#equals} and {@link TemplateEntry#hashCode}, including all subclasses.
+     */
+    @Test
+    public void testEqualsContract() {
+        TestUtils.assumeWorkingEqualsVerifier();
+        Set<Class<? extends TemplateEntry>> templates = TestUtils.getJosmSubtypes(TemplateEntry.class);
+        Assert.assertTrue(templates.size() >= 3); // if it finds less than 3 classes, something is broken
+        for (Class<?> c : templates) {
+            Logging.debug(c.toString());
+            EqualsVerifier.forClass(c).usingGetClass()
+                .suppress(Warning.NONFINAL_FIELDS, Warning.INHERITED_DIRECTLY_FROM_OBJECT)
+                .verify();
+        }
+    }
+}
