Index: /trunk/src/org/openstreetmap/josm/command/ChangeNodesCommand.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/ChangeNodesCommand.java	(revision 10662)
+++ /trunk/src/org/openstreetmap/josm/command/ChangeNodesCommand.java	(revision 10663)
@@ -38,4 +38,7 @@
         this.way = way;
         this.newNodes = newNodes;
+        if (newNodes.isEmpty()) {
+            throw new IllegalArgumentException("Cannot set nodes to be an empty list.");
+        }
     }
 
@@ -55,5 +58,5 @@
     @Override
     public String getDescriptionText() {
-        return tr("Changed nodes of {0}", way.getDisplayName(DefaultNameFormatter.getInstance()));
+        return tr("Change nodes of {0}", way.getDisplayName(DefaultNameFormatter.getInstance()));
     }
 
Index: /trunk/src/org/openstreetmap/josm/command/ChangePropertyCommand.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/ChangePropertyCommand.java	(revision 10662)
+++ /trunk/src/org/openstreetmap/josm/command/ChangePropertyCommand.java	(revision 10663)
@@ -156,5 +156,5 @@
             String msg;
             Map.Entry<String, String> entry = tags.entrySet().iterator().next();
-            if (entry.getValue() == null) {
+            if (entry.getValue() == null || entry.getValue().isEmpty()) {
                 switch(OsmPrimitiveType.from(primitive)) {
                 case NODE: msg = marktr("Remove \"{0}\" for node ''{1}''"); break;
@@ -175,5 +175,5 @@
         } else if (objects.size() > 1 && tags.size() == 1) {
             Map.Entry<String, String> entry = tags.entrySet().iterator().next();
-            if (entry.getValue() == null) {
+            if (entry.getValue() == null || entry.getValue().isEmpty()) {
                 /* I18n: plural form for objects, but value < 2 not possible! */
                 text = trn("Remove \"{0}\" for {1} object", "Remove \"{0}\" for {1} objects", objects.size(), entry.getKey(), objects.size());
@@ -186,5 +186,5 @@
             boolean allnull = true;
             for (Map.Entry<String, String> tag : this.tags.entrySet()) {
-                if (tag.getValue() != null) {
+                if (tag.getValue() != null && !tag.getValue().isEmpty()) {
                     allnull = false;
                     break;
@@ -226,5 +226,4 @@
                     return Collections.singleton(osm);
                 }
-
             });
         }
Index: /trunk/src/org/openstreetmap/josm/command/ChangePropertyKeyCommand.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/ChangePropertyKeyCommand.java	(revision 10662)
+++ /trunk/src/org/openstreetmap/josm/command/ChangePropertyKeyCommand.java	(revision 10663)
@@ -66,5 +66,5 @@
             return false; // save old
         for (OsmPrimitive osm : objects) {
-            if (osm.hasKeys()) {
+            if (osm.hasKey(key) || osm.hasKey(newKey)) {
                 osm.setModified(true);
                 String oldValue = osm.get(key);
@@ -87,7 +87,7 @@
             NameVisitor v = new NameVisitor();
             objects.get(0).accept(v);
-            text += ' '+tr(v.className)+' '+v.name;
+            text += " "+tr(v.className)+" "+v.name;
         } else {
-            text += ' '+objects.size()+' '+trn("object", "objects", objects.size());
+            text += " "+objects.size()+" "+trn("object", "objects", objects.size());
         }
         return text;
@@ -108,13 +108,15 @@
         for (final OsmPrimitive osm : objects) {
             osm.accept(v);
+            final String name = v.name;
+            final Icon icon = v.icon;
             children.add(new PseudoCommand() {
                 @Override
                 public String getDescriptionText() {
-                    return v.name;
+                    return name;
                 }
 
                 @Override
                 public Icon getDescriptionIcon() {
-                    return v.icon;
+                    return icon;
                 }
 
Index: /trunk/src/org/openstreetmap/josm/command/ChangeRelationMemberRoleCommand.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/ChangeRelationMemberRoleCommand.java	(revision 10662)
+++ /trunk/src/org/openstreetmap/josm/command/ChangeRelationMemberRoleCommand.java	(revision 10663)
@@ -49,5 +49,5 @@
     public boolean executeCommand() {
         if (position < 0 || position >= relation.getMembersCount())
-            return false;
+            return true;
 
         oldRole = relation.getMember(position).getRole();
@@ -62,7 +62,9 @@
     @Override
     public void undoCommand() {
-        relation.setMember(position, new RelationMember(oldRole, relation.getMember(position).getMember()));
-        if (oldModified != null) {
-            relation.setModified(oldModified);
+        if (position >= 0 && position < relation.getMembersCount()) {
+            relation.setMember(position, new RelationMember(oldRole, relation.getMember(position).getMember()));
+            if (oldModified != null) {
+                relation.setModified(oldModified);
+            }
         }
     }
Index: /trunk/src/org/openstreetmap/josm/command/Command.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/Command.java	(revision 10662)
+++ /trunk/src/org/openstreetmap/josm/command/Command.java	(revision 10663)
@@ -188,10 +188,8 @@
      * the removed layer)
      *
-     * @param oldLayer the old layer
-     * @return true if this command
+     * @param oldLayer the old layer that was removed
+     * @return true if this command is invalid after that layer is removed.
      */
     public boolean invalidBecauselayerRemoved(Layer oldLayer) {
-        if (!(oldLayer instanceof OsmDataLayer))
-            return false;
         return layer == oldLayer;
     }
Index: /trunk/src/org/openstreetmap/josm/command/DeleteCommand.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 10662)
+++ /trunk/src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 10663)
@@ -51,4 +51,32 @@
  */
 public class DeleteCommand extends Command {
+    private static final class DeleteChildCommand implements PseudoCommand {
+        private final OsmPrimitive osm;
+
+        private DeleteChildCommand(OsmPrimitive osm) {
+            this.osm = osm;
+        }
+
+        @Override
+        public String getDescriptionText() {
+            return tr("Deleted ''{0}''", osm.getDisplayName(DefaultNameFormatter.getInstance()));
+        }
+
+        @Override
+        public Icon getDescriptionIcon() {
+            return ImageProvider.get(osm.getDisplayType());
+        }
+
+        @Override
+        public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
+            return Collections.singleton(osm);
+        }
+
+        @Override
+        public String toString() {
+            return "DeleteChildCommand [osm=" + osm + "]";
+        }
+    }
+
     /**
      * The primitives that get deleted.
@@ -65,6 +93,4 @@
     public DeleteCommand(Collection<? extends OsmPrimitive> data) {
         CheckParameterUtil.ensureParameterNotNull(data, "data");
-        if (data.isEmpty())
-            throw new IllegalArgumentException(tr("At least one object to delete required, got empty collection"));
         this.toDelete = data;
         checkConsistency();
@@ -106,6 +132,4 @@
         super(layer);
         CheckParameterUtil.ensureParameterNotNull(data, "data");
-        if (data.isEmpty())
-            throw new IllegalArgumentException(tr("At least one object to delete required, got empty collection"));
         this.toDelete = data;
         checkConsistency();
@@ -113,4 +137,7 @@
 
     private void checkConsistency() {
+        if (toDelete.isEmpty()) {
+            throw new IllegalArgumentException(tr("At least one object to delete required, got empty collection"));
+        }
         for (OsmPrimitive p : toDelete) {
             if (p == null) {
@@ -216,19 +243,5 @@
             List<PseudoCommand> children = new ArrayList<>(toDelete.size());
             for (final OsmPrimitive osm : toDelete) {
-                children.add(new PseudoCommand() {
-
-                    @Override public String getDescriptionText() {
-                        return tr("Deleted ''{0}''", osm.getDisplayName(DefaultNameFormatter.getInstance()));
-                    }
-
-                    @Override public Icon getDescriptionIcon() {
-                        return ImageProvider.get(osm.getDisplayType());
-                    }
-
-                    @Override public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
-                        return Collections.singleton(osm);
-                    }
-
-                });
+                children.add(new DeleteChildCommand(osm));
             }
             return children;
@@ -441,4 +454,10 @@
     }
 
+    /**
+     * Create a command that deletes a single way segment. The way may be split by this.
+     * @param layer The layer the segment is in.
+     * @param ws The way segment that should be deleted
+     * @return A matching command to safely delete that segment.
+     */
     public static Command deleteWaySegment(OsmDataLayer layer, WaySegment ws) {
         if (ws.way.getNodesCount() < 3)
Index: /trunk/src/org/openstreetmap/josm/command/MoveCommand.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/MoveCommand.java	(revision 10662)
+++ /trunk/src/org/openstreetmap/josm/command/MoveCommand.java	(revision 10663)
@@ -243,4 +243,12 @@
     public Collection<Node> getParticipatingPrimitives() {
         return nodes;
+    }
+
+    /**
+     * Gets the offset.
+     * @return The current offset.
+     */
+    protected EastNorth getOffset() {
+        return new EastNorth(x, y);
     }
 
Index: /trunk/src/org/openstreetmap/josm/command/RotateCommand.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/RotateCommand.java	(revision 10662)
+++ /trunk/src/org/openstreetmap/josm/command/RotateCommand.java	(revision 10663)
@@ -39,5 +39,5 @@
      * @param currentEN cuurent eats/north
      */
-    public RotateCommand(Collection<OsmPrimitive> objects, EastNorth currentEN) {
+    public RotateCommand(Collection<? extends OsmPrimitive> objects, EastNorth currentEN) {
         super(objects);
 
@@ -71,11 +71,19 @@
 
     /**
+     * Set the rotation angle.
+     * @param rotationAngle The rotate angle
+     */
+    protected void setRotationAngle(double rotationAngle) {
+        this.rotationAngle = rotationAngle;
+    }
+
+    /**
      * Rotate nodes.
      */
     @Override
     protected void transformNodes() {
+        double cosPhi = Math.cos(rotationAngle);
+        double sinPhi = Math.sin(rotationAngle);
         for (Node n : nodes) {
-            double cosPhi = Math.cos(rotationAngle);
-            double sinPhi = Math.sin(rotationAngle);
             EastNorth oldEastNorth = oldStates.get(n).getEastNorth();
             double x = oldEastNorth.east() - pivot.east();
Index: /trunk/src/org/openstreetmap/josm/command/ScaleCommand.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/ScaleCommand.java	(revision 10662)
+++ /trunk/src/org/openstreetmap/josm/command/ScaleCommand.java	(revision 10663)
@@ -35,5 +35,5 @@
      * @param currentEN cuurent eats/north
      */
-    public ScaleCommand(Collection<OsmPrimitive> objects, EastNorth currentEN) {
+    public ScaleCommand(Collection<? extends OsmPrimitive> objects, EastNorth currentEN) {
         super(objects);
 
@@ -58,6 +58,14 @@
         double startDistance = pivot.distance(startEN);
         double currentDistance = pivot.distance(currentEN);
-        scalingFactor = Math.cos(startAngle-endAngle) * currentDistance / startDistance;
+        setScalingFactor(Math.cos(startAngle-endAngle) * currentDistance / startDistance);
         transformNodes();
+    }
+
+    /**
+     * Set the scaling factor
+     * @param scalingFactor The scaling factor.
+     */
+    protected void setScalingFactor(double scalingFactor) {
+        this.scalingFactor = scalingFactor;
     }
 
Index: /trunk/src/org/openstreetmap/josm/command/SelectCommand.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/SelectCommand.java	(revision 10662)
+++ /trunk/src/org/openstreetmap/josm/command/SelectCommand.java	(revision 10663)
@@ -5,4 +5,6 @@
 
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.Objects;
 
@@ -28,5 +30,9 @@
      */
     public SelectCommand(Collection<OsmPrimitive> newSelection) {
-        this.newSelection = newSelection;
+        if (newSelection == null || newSelection.isEmpty()) {
+            this.newSelection = Collections.emptySet();
+        } else {
+            this.newSelection = new HashSet<>(newSelection);
+        }
     }
 
Index: /trunk/src/org/openstreetmap/josm/command/TransformNodesCommand.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/TransformNodesCommand.java	(revision 10662)
+++ /trunk/src/org/openstreetmap/josm/command/TransformNodesCommand.java	(revision 10663)
@@ -49,5 +49,5 @@
      * @param objects objects to fetch nodes from
      */
-    public TransformNodesCommand(Collection<OsmPrimitive> objects) {
+    public TransformNodesCommand(Collection<? extends OsmPrimitive> objects) {
         this.nodes = AllNodesVisitor.getAllNodes(objects);
         storeOldState();
Index: /trunk/test/unit/org/openstreetmap/josm/command/AddCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/AddCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/AddCommandTest.java	(revision 10663)
@@ -2,13 +2,23 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.User;
+import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -20,9 +30,104 @@
 
     /**
-     * Setup test.
+     * We need prefs for nodes.
      */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().i18n();
+
+    /**
+     * Test if the add command is executed correctly and sets the modified flag.
+     */
+    @Test
+    public void testAdd() {
+        OsmDataLayer layer1 = new OsmDataLayer(new DataSet(), "l1", null);
+        Main.getLayerManager().addLayer(layer1);
+        assertArrayEquals(new Object[0], layer1.data.allPrimitives().toArray());
+
+        Node osm = new Node(LatLon.ZERO);
+        assertTrue(new AddCommand(osm).executeCommand());
+
+        assertArrayEquals(new Object[] {osm}, layer1.data.allPrimitives().toArray());
+        assertArrayEquals(new Object[] {osm}, layer1.data.allModifiedPrimitives().toArray());
+        assertTrue(osm.isModified());
+    }
+
+    /**
+     * Tests if the add command respects the layer.
+     */
+    @Test
+    public void testAddToLayer() {
+        OsmDataLayer layer1 = new OsmDataLayer(new DataSet(), "l1", null);
+        OsmDataLayer layer2 = new OsmDataLayer(new DataSet(), "l1", null);
+
+        Main.getLayerManager().addLayer(layer1);
+        Main.getLayerManager().addLayer(layer2);
+
+        Node osm = new Node(LatLon.ZERO);
+        assertTrue(new AddCommand(layer2, osm).executeCommand());
+
+        assertArrayEquals(new Object[0], layer1.data.allPrimitives().toArray());
+        assertArrayEquals(new Object[] {osm}, layer2.data.allPrimitives().toArray());
+    }
+
+    /**
+     * Test {@link AddCommand#undoCommand()}
+     */
+    @Test
+    public void testUndo() {
+        OsmDataLayer layer1 = new OsmDataLayer(new DataSet(), "l1", null);
+        Main.getLayerManager().addLayer(layer1);
+        Node osm = new Node(LatLon.ZERO);
+        layer1.data.addPrimitive(osm);
+
+        AddCommand command = new AddCommand(new Node(LatLon.ZERO));
+        command.executeCommand();
+
+        command.undoCommand();
+        assertArrayEquals(new Object[] {osm}, layer1.data.allPrimitives().toArray());
+    }
+
+    /**
+     * Test {@link AddCommand#getParticipatingPrimitives()}
+     */
+    @Test
+    public void testParticipatingPrimitives() {
+        Node osm = new Node(LatLon.ZERO);
+
+        assertArrayEquals(new Object[] {osm}, new AddCommand(osm).getParticipatingPrimitives().toArray());
+    }
+
+    /**
+     * Tests {@link AddCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     */
+    @Test
+    public void testFillModifiedData() {
+        Node osm = new Node(LatLon.ZERO);
+
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+        new AddCommand(osm).fillModifiedData(modified, deleted, added);
+        assertArrayEquals(new Object[] {}, modified.toArray());
+        assertArrayEquals(new Object[] {}, deleted.toArray());
+        assertArrayEquals(new Object[] {osm}, added.toArray());
+   }
+
+    /**
+     * Test {@link AddCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        Node node = new Node(LatLon.ZERO);
+        node.put("name", "xy");
+        Way way = new Way();
+        way.addNode(node);
+        way.put("name", "xy");
+        Relation relation = new Relation();
+        relation.put("name", "xy");
+
+        assertTrue(new AddCommand(node).getDescriptionText().matches("Add node.*xy.*"));
+        assertTrue(new AddCommand(way).getDescriptionText().matches("Add way.*xy.*"));
+        assertTrue(new AddCommand(relation).getDescriptionText().matches("Add relation.*xy.*"));
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/command/AddPrimitivesCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/AddPrimitivesCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/AddPrimitivesCommandTest.java	(revision 10663)
@@ -2,11 +2,31 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.NodeData;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.PrimitiveData;
 import org.openstreetmap.josm.data.osm.User;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.WayData;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -18,9 +38,217 @@
 
     /**
-     * Setup test.
-     */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+     * We need prefs for nodes.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().i18n();
+
+    /**
+     * Test if the add command is executed correctly and does not set the modified flag.
+     */
+    @Test
+    public void testAdd() {
+        OsmDataLayer layer1 = new OsmDataLayer(new DataSet(), "l1", null);
+        Main.getLayerManager().addLayer(layer1);
+
+        List<PrimitiveData> testData = createTestData();
+        assertTrue(new AddPrimitivesCommand(testData).executeCommand());
+
+        testContainsTestData(layer1);
+        assertEquals(3, layer1.data.getAllSelected().size());
+    }
+
+    /**
+     * Test if the add command sets the selection.
+     */
+    @Test
+    public void testAddSetSelection() {
+        OsmDataLayer layer1 = new OsmDataLayer(new DataSet(), "l1", null);
+        Main.getLayerManager().addLayer(layer1);
+
+        List<PrimitiveData> testData = createTestData();
+        assertTrue(new AddPrimitivesCommand(testData, testData.subList(2, 3)).executeCommand());
+
+        testContainsTestData(layer1);
+
+        assertEquals(1, layer1.data.getAllSelected().size());
+        assertEquals(1, layer1.data.getSelectedWays().size());
+    }
+
+    /**
+     * Tests if the add command respects the layer.
+     */
+    @Test
+    public void testAddToLayer() {
+        OsmDataLayer layer1 = new OsmDataLayer(new DataSet(), "l1", null);
+        OsmDataLayer layer2 = new OsmDataLayer(new DataSet(), "l1", null);
+
+        Main.getLayerManager().addLayer(layer1);
+        Main.getLayerManager().addLayer(layer2);
+
+        List<PrimitiveData> testData = createTestData();
+        assertTrue(new AddPrimitivesCommand(testData, testData.subList(2, 3), layer1).executeCommand());
+
+        testContainsTestData(layer1);
+        assertTrue(layer2.data.allPrimitives().isEmpty());
+
+        assertEquals(1, layer1.data.getAllSelected().size());
+        assertEquals(1, layer1.data.getSelectedWays().size());
+    }
+
+    /**
+     * Tests if the add command ignores existing data
+     */
+    @Test
+    public void testAddIgnoresExisting() {
+        OsmDataLayer layer1 = new OsmDataLayer(new DataSet(), "l1", null);
+        Main.getLayerManager().addLayer(layer1);
+
+        List<PrimitiveData> testData = createTestData();
+        assertTrue(new AddPrimitivesCommand(testData).executeCommand());
+        assertEquals(2, layer1.data.getNodes().size());
+        assertEquals(1, layer1.data.getWays().size());
+
+        testData.set(2, createTestNode(7));
+        assertTrue(new AddPrimitivesCommand(testData).executeCommand());
+
+        assertEquals(3, layer1.data.getNodes().size());
+        assertEquals(1, layer1.data.getWays().size());
+    }
+
+    /**
+     * Test {@link AddPrimitivesCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        OsmDataLayer layer1 = new OsmDataLayer(new DataSet(), "l1", null);
+        Main.getLayerManager().addLayer(layer1);
+
+        List<PrimitiveData> testData = createTestData();
+        NodeData data2 = createTestNode(7);
+
+        AddPrimitivesCommand command1 = new AddPrimitivesCommand(testData);
+        AddPrimitivesCommand command2 = new AddPrimitivesCommand(Arrays.<PrimitiveData>asList(data2));
+
+        assertEquals("Added 3 objects", command1.getDescriptionText());
+        assertEquals("Added 1 object", command2.getDescriptionText());
+
+        // Name must be the same after execution.
+        assertTrue(command1.executeCommand());
+        assertTrue(command2.executeCommand());
+
+        assertEquals("Added 3 objects", command1.getDescriptionText());
+        assertEquals("Added 1 object", command2.getDescriptionText());
+    }
+
+    /**
+     * Test {@link AddPrimitivesCommand#undoCommand()}
+     */
+    @Test
+    public void testUndo() {
+        OsmDataLayer layer1 = new OsmDataLayer(new DataSet(), "l1", null);
+        Main.getLayerManager().addLayer(layer1);
+
+        List<PrimitiveData> testData = createTestData();
+
+        AddPrimitivesCommand command = new AddPrimitivesCommand(testData);
+
+        assertTrue(command.executeCommand());
+
+        assertEquals(3, layer1.data.allPrimitives().size());
+        assertEquals(1, layer1.data.getWays().size());
+        Way way = layer1.data.getWays().iterator().next();
+
+        for (int i = 0; i < 2; i++) {
+            // Needs to work multiple times.
+            command.undoCommand();
+
+            assertEquals(0, layer1.data.allPrimitives().size());
+            assertEquals(0, layer1.data.getWays().size());
+
+            // redo
+            assertTrue(command.executeCommand());
+
+            assertEquals(3, layer1.data.allPrimitives().size());
+            assertEquals(1, layer1.data.getWays().size());
+            assertSame(way, layer1.data.getWays().iterator().next());
+        }
+    }
+
+    /**
+     * Test {@link AddCommand#getParticipatingPrimitives()}
+     */
+    @Test
+    public void testParticipatingPrimitives() {
+        OsmDataLayer layer1 = new OsmDataLayer(new DataSet(), "l1", null);
+        Main.getLayerManager().addLayer(layer1);
+
+        List<PrimitiveData> testData = createTestData();
+        AddPrimitivesCommand command = new AddPrimitivesCommand(testData);
+        assertTrue(command.executeCommand());
+
+        assertEquals(3, command.getParticipatingPrimitives().size());
+        HashSet<OsmPrimitive> should = new HashSet<>(layer1.data.allPrimitives());
+        assertEquals(should, new HashSet<>(command.getParticipatingPrimitives()));
+
+        // needs to be the same after undo
+        command.undoCommand();
+        assertEquals(should, new HashSet<>(command.getParticipatingPrimitives()));
+    }
+
+    /**
+     * Tests {@link AddPrimitivesCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     */
+    @Test
+    public void testFillModifiedData() {
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+
+        List<PrimitiveData> testData = createTestData();
+        new AddPrimitivesCommand(testData).fillModifiedData(modified, deleted, added);
+
+        assertArrayEquals(new Object[] {}, modified.toArray());
+        assertArrayEquals(new Object[] {}, deleted.toArray());
+        assertArrayEquals(new Object[] {}, added.toArray());
+    }
+
+    private void testContainsTestData(OsmDataLayer layer1) {
+        assertEquals(3, layer1.data.allPrimitives().size());
+        assertEquals(2, layer1.data.getNodes().size());
+        assertEquals(1, layer1.data.getWays().size());
+        assertEquals(0, layer1.data.allModifiedPrimitives().size());
+        for (OsmPrimitive n : layer1.data.allPrimitives()) {
+            assertEquals("test", n.get("test"));
+            assertFalse(n.isModified());
+        }
+
+        for (Node n : layer1.data.getNodes()) {
+            assertEquals(LatLon.ZERO, n.getCoor());
+        }
+
+        for (Way w : layer1.data.getWays()) {
+            assertEquals(2, w.getNodes().size());
+            assertEquals(5, w.getNode(0).getId());
+            assertEquals(6, w.getNode(1).getId());
+        }
+    }
+
+    private List<PrimitiveData> createTestData() {
+        NodeData node1 = createTestNode(5);
+        NodeData node2 = createTestNode(6);
+        WayData way = new WayData();
+        way.put("test", "test");
+        way.setNodes(Arrays.asList(node1.getId(), node2.getId()));
+        List<PrimitiveData> testData = Arrays.<PrimitiveData>asList(node1, node2, way);
+        return testData;
+    }
+
+    private NodeData createTestNode(int id) {
+        NodeData node1 = new NodeData();
+        node1.setCoor(LatLon.ZERO);
+        node1.put("test", "test");
+        node1.setId(id);
+        return node1;
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/command/ChangeCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/ChangeCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/ChangeCommandTest.java	(revision 10663)
@@ -2,13 +2,29 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.command.CommandTest.CommandTestData;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.DataIntegrityProblemException;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.User;
+import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -20,9 +36,114 @@
 
     /**
-     * Setup test.
+     * We need prefs for nodes.
      */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().i18n();
+    private CommandTestData testData;
+
+    /**
+     * Set up the test data.
+     */
+    @Before
+    public void createTestData() {
+        testData = new CommandTestData();
+    }
+
+    /**
+     * Test that empty ways are prevented.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testPreventEmptyWays() {
+        Way emptyWay = new Way();
+        new ChangeCommand(testData.existingWay, emptyWay);
+    }
+
+    /**
+     * Test {@link ChangeCommand#executeCommand()}
+     */
+    @Test
+    public void testChange() {
+        Node newNode = new Node(5);
+        newNode.setCoor(LatLon.NORTH_POLE);
+        newNode.put("new", "new");
+
+        new ChangeCommand(testData.existingNode, newNode).executeCommand();
+
+        assertEquals("new", testData.existingNode.get("new"));
+        assertEquals(null, testData.existingNode.get("existing"));
+        assertEquals(LatLon.NORTH_POLE, testData.existingNode.getCoor());
+
+        Way newWay = new Way(10);
+        List<Node> newNodes = testData.existingWay.getNodes();
+        Collections.reverse(newNodes);
+        newWay.setNodes(newNodes);
+
+        new ChangeCommand(testData.existingWay, newWay).executeCommand();
+        assertArrayEquals(newNodes.toArray(), testData.existingWay.getNodes().toArray());
+    }
+
+    /**
+     * Test {@link ChangeCommand#executeCommand()} fails if ID is changed
+     */
+    @Test(expected = DataIntegrityProblemException.class)
+    public void testChangeIdChange() {
+        Node newNode = new Node(1);
+        newNode.setCoor(LatLon.NORTH_POLE);
+
+        new ChangeCommand(testData.existingNode, newNode).executeCommand();
+    }
+
+    /**
+     * Test {@link ChangeCommand#undoCommand()}
+     */
+    @Test
+    public void testUndo() {
+        Node newNode = new Node(5);
+        newNode.setCoor(LatLon.NORTH_POLE);
+        newNode.put("new", "new");
+
+        ChangeCommand command = new ChangeCommand(testData.existingNode, newNode);
+        command.executeCommand();
+
+        assertEquals("new", testData.existingNode.get("new"));
+        assertEquals(LatLon.NORTH_POLE, testData.existingNode.getCoor());
+
+        command.undoCommand();
+        assertNull(testData.existingNode.get("new"));
+        assertEquals("existing", testData.existingNode.get("existing"));
+        assertEquals(LatLon.ZERO, testData.existingNode.getCoor());
+    }
+
+    /**
+     * Tests {@link ChangeCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     */
+    @Test
+    public void testFillModifiedData() {
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+        new ChangeCommand(testData.existingNode, testData.existingNode).fillModifiedData(modified, deleted, added);
+        assertArrayEquals(new Object[] {testData.existingNode}, modified.toArray());
+        assertArrayEquals(new Object[] {}, deleted.toArray());
+        assertArrayEquals(new Object[] {}, added.toArray());
+    }
+
+    /**
+     * Test {@link ChangeCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        Node node = new Node(LatLon.ZERO);
+        node.put("name", "xy");
+        Way way = new Way();
+        way.addNode(node);
+        way.put("name", "xy");
+        Relation relation = new Relation();
+        relation.put("name", "xy");
+
+        assertTrue(new ChangeCommand(node, node).getDescriptionText().matches("Change node.*xy.*"));
+        assertTrue(new ChangeCommand(way, way).getDescriptionText().matches("Change way.*xy.*"));
+        assertTrue(new ChangeCommand(relation, relation).getDescriptionText().matches("Change relation.*xy.*"));
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/command/ChangeNodesCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/ChangeNodesCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/ChangeNodesCommandTest.java	(revision 10663)
@@ -2,12 +2,28 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.command.CommandTest.CommandTestData;
+import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -19,9 +35,87 @@
 
     /**
-     * Setup test.
+     * We need prefs for nodes.
      */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().i18n();
+    private CommandTestData testData;
+
+    /**
+     * Set up the test data.
+     */
+    @Before
+    public void createTestData() {
+        testData = new CommandTestData();
+    }
+
+    /**
+     * Test that empty ways are prevented.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testPreventEmptyWays() {
+        new ChangeNodesCommand(testData.existingWay, Collections.<Node>emptyList());
+    }
+
+    /**
+     * Test {@link ChangeNodesCommand#executeCommand()}
+     */
+    @Test
+    public void testChange() {
+        List<Node> newNodes = testData.existingWay.getNodes();
+        Collections.reverse(newNodes);
+
+        new ChangeNodesCommand(testData.existingWay, newNodes).executeCommand();
+        assertArrayEquals(newNodes.toArray(), testData.existingWay.getNodes().toArray());
+
+        // tags are unchanged
+        assertEquals("existing", testData.existingWay.get("existing"));
+        assertTrue(testData.existingWay.isModified());
+    }
+
+    /**
+     * Test {@link ChangeCommand#undoCommand()}
+     */
+    @Test
+    public void testUndo() {
+        List<Node> newNodes = testData.existingWay.getNodes();
+        Collections.reverse(newNodes);
+
+        ChangeNodesCommand command = new ChangeNodesCommand(testData.existingWay, newNodes);
+        command.executeCommand();
+        command.undoCommand();
+        Collections.reverse(newNodes);
+        assertArrayEquals(newNodes.toArray(), testData.existingWay.getNodes().toArray());
+        assertFalse(testData.existingWay.isModified());
+    }
+
+    /**
+     * Tests {@link ChangeNodesCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     */
+    @Test
+    public void testFillModifiedData() {
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+        new ChangeNodesCommand(testData.existingWay, Arrays.asList(testData.existingNode)).fillModifiedData(modified,
+                deleted, added);
+        assertArrayEquals(new Object[] {testData.existingWay}, modified.toArray());
+        assertArrayEquals(new Object[] {}, deleted.toArray());
+        assertArrayEquals(new Object[] {}, added.toArray());
+    }
+
+    /**
+     * Test {@link ChangeNodesCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        Node node = new Node(LatLon.ZERO);
+        node.put("name", "xy");
+        Way way = new Way();
+        way.addNode(node);
+        way.put("name", "xy");
+
+        assertTrue(
+                new ChangeNodesCommand(way, Arrays.asList(node)).getDescriptionText().matches("Change nodes of.*xy.*"));
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/command/ChangePropertyCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/ChangePropertyCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/ChangePropertyCommandTest.java	(revision 10663)
@@ -2,11 +2,31 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.command.CommandTest.CommandTestData;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.TagMap;
 import org.openstreetmap.josm.data.osm.User;
+import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -18,9 +38,238 @@
 
     /**
-     * Setup test.
-     */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+     * We need prefs for nodes.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().i18n();
+    private CommandTestData testData;
+
+    /**
+     * Set up the test data.
+     */
+    @Before
+    public void createTestData() {
+        testData = new CommandTestData();
+    }
+
+    /**
+     * Checks that the short constructors create the right {@link ChangePropertyCommand}
+     */
+    @Test
+    public void testShortConstructor() {
+        ChangePropertyCommand command = new ChangePropertyCommand(Arrays.asList(testData.existingNode), "a", "b");
+        assertEquals("b", command.getTags().get("a"));
+        assertEquals(1, command.getTags().size());
+        assertEquals(1, command.getObjectsNumber());
+
+        command = new ChangePropertyCommand(testData.existingNode, "a", "b");
+        assertEquals("b", command.getTags().get("a"));
+        assertEquals(1, command.getTags().size());
+        assertEquals(1, command.getObjectsNumber());
+    }
+
+    /**
+     * Checks that {@link ChangePropertyCommand} adds/updates a property
+     */
+    @Test
+    public void testUpdateSingleProperty() {
+        Node node1 = testData.createNode(14);
+        Node node2 = testData.createNode(15);
+        node2.removeAll();
+
+        TagMap tags = new TagMap();
+        tags.put("existing", "new");
+        new ChangePropertyCommand(Arrays.<OsmPrimitive>asList(node1, node2), tags).executeCommand();
+        assertEquals("new", node1.get("existing"));
+        assertEquals("new", node2.get("existing"));
+
+        assertTrue(node1.isModified());
+        assertTrue(node2.isModified());
+    }
+
+    /**
+     * Checks that {@link ChangePropertyCommand} removes a property
+     */
+    @Test
+    public void testRemoveProperty() {
+        Node node1 = testData.createNode(14);
+        Node node2 = testData.createNode(15);
+        node2.removeAll();
+
+        HashMap<String, String> tags = new HashMap<>();
+        tags.put("existing", "");
+        new ChangePropertyCommand(Arrays.<OsmPrimitive>asList(node1, node2), tags).executeCommand();
+        assertNull(node1.get("existing"));
+        assertNull(node2.get("existing"));
+
+        assertTrue(node1.isModified());
+        assertFalse(node2.isModified());
+    }
+
+    /**
+     * Checks that {@link ChangePropertyCommand} adds/updates multiple properties
+     */
+    @Test
+    public void testUpdateMultipleProperties() {
+        Node node1 = testData.createNode(14);
+        Node node2 = testData.createNode(15);
+        node2.removeAll();
+        node2.put("test", "xx");
+        node2.put("remove", "xx");
+
+        HashMap<String, String> tags = new HashMap<>();
+        tags.put("existing", "existing");
+        tags.put("test", "test");
+        tags.put("remove", "");
+        new ChangePropertyCommand(Arrays.<OsmPrimitive>asList(node1, node2), tags).executeCommand();
+        assertEquals("existing", node1.get("existing"));
+        assertEquals("existing", node2.get("existing"));
+        assertEquals("test", node1.get("test"));
+        assertEquals("test", node2.get("test"));
+        assertNull(node1.get("remove"));
+        assertNull(node2.get("remove"));
+
+        assertTrue(node1.isModified());
+        assertTrue(node2.isModified());
+    }
+
+    /**
+     * Checks that {@link ChangePropertyCommand} adds/updates a property
+     */
+    @Test
+    public void testUpdateIgnoresExistingProperty() {
+        Node node1 = testData.createNode(14);
+        Node node2 = testData.createNode(15);
+        node2.removeAll();
+
+        TagMap tags = new TagMap();
+        tags.put("existing", "existing");
+        new ChangePropertyCommand(Arrays.<OsmPrimitive>asList(node1, node2), tags).executeCommand();
+        assertEquals("existing", node1.get("existing"));
+        assertEquals("existing", node2.get("existing"));
+
+        assertFalse(node1.isModified());
+        assertTrue(node2.isModified());
+    }
+
+    /**
+     * Tests {@link ChangePropertyCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     * and {@link ChangePropertyCommand#getObjectsNumber()}
+     */
+    @Test
+    public void testFillModifiedData() {
+        Node node1 = testData.createNode(14);
+        Node node2 = testData.createNode(15);
+        node2.put("existing", "new");
+
+        TagMap tags = new TagMap();
+        tags.put("existing", "new");
+
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+        new ChangePropertyCommand(Arrays.asList(node1, node2), tags).fillModifiedData(modified, deleted, added);
+        assertArrayEquals(new Object[] {node1}, modified.toArray());
+        assertArrayEquals(new Object[] {}, deleted.toArray());
+        assertArrayEquals(new Object[] {}, added.toArray());
+
+        assertEquals(1, new ChangePropertyCommand(Arrays.asList(node1, node2), tags).getObjectsNumber());
+
+        tags.clear();
+        assertEquals(0, new ChangePropertyCommand(Arrays.asList(node1, node2), tags).getObjectsNumber());
+
+        tags.put("a", "b");
+        assertEquals(2, new ChangePropertyCommand(Arrays.asList(node1, node2), tags).getObjectsNumber());
+    }
+
+    /**
+     * Test {@link ChangePropertyCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        Node node1 = testData.createNode(14);
+        Node node2 = testData.createNode(15);
+        Node node3 = testData.createNode(16);
+        node1.put("name", "xy");
+        node2.put("existing", "new");
+        node3.put("existing", null);
+
+        TagMap tags = new TagMap();
+        tags.put("existing", "new");
+
+        HashMap<String, String> tagsRemove = new HashMap<>();
+        tagsRemove.put("existing", "");
+
+        Way way = new Way();
+        way.addNode(node1);
+        way.put("name", "xy");
+        way.put("existing", "existing");
+        Relation relation = new Relation();
+        relation.put("name", "xy");
+        relation.put("existing", "existing");
+
+        // nop
+        assertTrue(new ChangePropertyCommand(Arrays.asList(node2), tags).getDescriptionText()
+                .matches("Set.*tags for 0 objects"));
+
+        // change 1 key on 1 element.
+        assertTrue(new ChangePropertyCommand(Arrays.asList(node1, node2), tags).getDescriptionText()
+                .matches("Set existing=new for node.*xy.*"));
+        assertTrue(new ChangePropertyCommand(Arrays.asList(way, node2), tags).getDescriptionText()
+                .matches("Set existing=new for way.*xy.*"));
+        assertTrue(new ChangePropertyCommand(Arrays.asList(relation, node2), tags).getDescriptionText()
+                .matches("Set existing=new for relation.*xy.*"));
+
+        // remove 1 key on 1 element
+        assertTrue(new ChangePropertyCommand(Arrays.asList(node1, node3), tagsRemove).getDescriptionText()
+                .matches("Remove \"existing\" for node.*xy.*"));
+        assertTrue(new ChangePropertyCommand(Arrays.asList(way, node3), tagsRemove).getDescriptionText()
+                .matches("Remove \"existing\" for way.*xy.*"));
+        assertTrue(new ChangePropertyCommand(Arrays.asList(relation, node3), tagsRemove).getDescriptionText()
+                .matches("Remove \"existing\" for relation.*xy.*"));
+
+        // change 1 key on 3 elements
+        assertEquals("Set existing=new for 3 objects",
+                new ChangePropertyCommand(Arrays.asList(node1, node2, way, relation), tags).getDescriptionText());
+        // remove 1 key on 3 elements
+        assertEquals("Remove \"existing\" for 3 objects",
+                new ChangePropertyCommand(Arrays.asList(node1, node3, way, relation), tagsRemove).getDescriptionText());
+
+        // add 2 keys on 3 elements
+        tags.put("name", "a");
+        node2.put("name", "a");
+        assertEquals("Set 2 tags for 3 objects",
+                new ChangePropertyCommand(Arrays.asList(node1, node2, way, relation), tags).getDescriptionText());
+
+        tagsRemove.put("name", "");
+        // remove 2 key on 3 elements
+        assertEquals("Deleted 2 tags for 3 objects",
+                new ChangePropertyCommand(Arrays.asList(node1, node3, way, relation), tagsRemove).getDescriptionText());
+    }
+
+    /**
+     * Test {@link ChangePropertyCommand#getChildren()}
+     */
+    @Test
+    public void testChildren() {
+        Node node1 = testData.createNode(15);
+        Node node2 = testData.createNode(16);
+        node1.put("name", "node1");
+        node2.put("name", "node2");
+
+        assertNull(new ChangePropertyCommand(Arrays.asList(node1), "a", "b").getChildren());
+
+        Collection<PseudoCommand> children = new ChangePropertyCommand(Arrays.asList(node1, node2), "a", "b").getChildren();
+        assertEquals(2, children.size());
+        List<Node> nodesToExpect = new ArrayList<>(Arrays.asList(node1, node2));
+        for (PseudoCommand c : children) {
+            assertNull(c.getChildren());
+            Collection<? extends OsmPrimitive> part = c.getParticipatingPrimitives();
+            assertEquals(1, part.size());
+            OsmPrimitive node = part.iterator().next();
+            assertTrue(nodesToExpect.remove(node));
+
+            assertTrue(c.getDescriptionText().matches(".*" + node.get("name") + ".*"));
+        }
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/command/ChangePropertyKeyCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/ChangePropertyKeyCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/ChangePropertyKeyCommandTest.java	(revision 10663)
@@ -2,11 +2,25 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.command.CommandTest.CommandTestData;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -18,9 +32,114 @@
 
     /**
-     * Setup test.
+     * We need prefs for nodes.
      */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().i18n();
+    private CommandTestData testData;
+
+    /**
+     * Set up the test data.
+     */
+    @Before
+    public void createTestData() {
+        testData = new CommandTestData();
+    }
+
+    /**
+     * Tests that a key is changed.
+     */
+    @Test
+    public void testChangeKeySingle() {
+        assertTrue(new ChangePropertyKeyCommand(testData.existingNode, "existing", "newKey").executeCommand());
+
+        assertNull(testData.existingNode.get("existing"));
+        assertEquals("existing", testData.existingNode.get("newKey"));
+        assertTrue(testData.existingNode.isModified());
+    }
+
+    /**
+     * Tests that a key is changed.
+     */
+    @Test
+    public void testChangeKey() {
+        assertTrue(new ChangePropertyKeyCommand(Arrays.asList(testData.existingNode, testData.existingWay), "existing",
+                "newKey").executeCommand());
+
+        assertNull(testData.existingNode.get("existing"));
+        assertEquals("existing", testData.existingNode.get("newKey"));
+        assertTrue(testData.existingNode.isModified());
+        assertNull(testData.existingWay.get("existing"));
+        assertEquals("existing", testData.existingWay.get("newKey"));
+        assertTrue(testData.existingWay.isModified());
+    }
+
+    /**
+     * Tests that nop operations are ignored.
+     */
+    @Test
+    public void testChangeKeyIgnored() {
+        Node node1 = testData.createNode(15);
+        node1.removeAll();
+        Node node2 = testData.createNode(16);
+        Node node3 = testData.createNode(17);
+
+        assertTrue(new ChangePropertyKeyCommand(Arrays.asList(node1, node2), "nonexisting", "newKey").executeCommand());
+
+        assertFalse(node1.isModified());
+        assertFalse(node2.isModified());
+
+        assertTrue(new ChangePropertyKeyCommand(Arrays.asList(node1, node2), "existing", "newKey").executeCommand());
+
+        assertFalse(node1.isModified());
+        assertTrue(node2.isModified());
+
+        // removes existing
+        assertTrue(new ChangePropertyKeyCommand(Arrays.asList(node1, node3), "newKey", "existing").executeCommand());
+
+        assertFalse(node1.isModified());
+        assertTrue(node3.isModified());
+        assertNull(node3.get("newKey"));
+        assertNull(node3.get("existing"));
+    }
+
+    /**
+     * Test {@link ChangePropertyKeyCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        Node node1 = testData.createNode(15);
+        node1.put("name", "xy");
+
+        assertTrue(new ChangePropertyKeyCommand(node1, "a", "b").getDescriptionText()
+                .matches("Replace \"a\" by \"b\" for.*xy.*"));
+        assertTrue(new ChangePropertyKeyCommand(Arrays.asList(node1, testData.existingNode), "a", "b")
+                .getDescriptionText().matches("Replace \"a\" by \"b\" for 2 objects"));
+    }
+
+    /**
+     * Test {@link ChangePropertyCommand#getChildren()}
+     */
+    @Test
+    public void testChildren() {
+        Node node1 = testData.createNode(15);
+        Node node2 = testData.createNode(16);
+        node1.put("name", "node1");
+        node2.put("name", "node2");
+
+        ArrayList<Node> nodesToExpect = new ArrayList<>(Arrays.asList(node1, node2));
+
+        assertNull(new ChangePropertyKeyCommand(node1, "a", "b").getChildren());
+        Collection<PseudoCommand> children = new ChangePropertyKeyCommand(Arrays.asList(node1, node2), "a", "b").getChildren();
+        assertEquals(2, children.size());
+        for (PseudoCommand c : children) {
+            assertNull(c.getChildren());
+            Collection<? extends OsmPrimitive> part = c.getParticipatingPrimitives();
+            assertEquals(1, part.size());
+            OsmPrimitive node = part.iterator().next();
+            assertTrue(nodesToExpect.remove(node));
+
+            assertTrue(c.getDescriptionText().contains(node.getName()));
+        }
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/command/ChangeRelationMemberRoleCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/ChangeRelationMemberRoleCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/ChangeRelationMemberRoleCommandTest.java	(revision 10663)
@@ -2,12 +2,24 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.command.CommandTest.CommandTestDataWithRelation;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -19,9 +31,112 @@
 
     /**
-     * Setup test.
+     * We need prefs for nodes.
      */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().i18n();
+    private CommandTestDataWithRelation testData;
+
+    /**
+     * Set up the test data.
+     */
+    @Before
+    public void createTestData() {
+        testData = new CommandTestDataWithRelation();
+    }
+
+    /**
+     * Test if {@link ChangeRelationMemberRoleCommand} changes the role by index
+     */
+    @Test
+    public void testRoleChanged() {
+        assertTrue(new ChangeRelationMemberRoleCommand(testData.existingRelation, 0, "newRole").executeCommand());
+        assertEquals("newRole", testData.existingRelation.getMember(0).getRole());
+        assertEquals(testData.existingNode, testData.existingRelation.getMember(0).getMember());
+        assertEquals("way", testData.existingRelation.getMember(1).getRole());
+
+        assertTrue(testData.existingRelation.isModified());
+
+        assertTrue(new ChangeRelationMemberRoleCommand(testData.existingRelation, 1, "newRole").executeCommand());
+        assertEquals("newRole", testData.existingRelation.getMember(1).getRole());
+    }
+
+    /**
+     * Wrong index should be ignored.
+     */
+    @Test
+    public void testWrongIndex() {
+        // should be ignored
+        ChangeRelationMemberRoleCommand command1 = new ChangeRelationMemberRoleCommand(testData.existingRelation, -1, "newRole");
+        assertTrue(command1.executeCommand());
+        ChangeRelationMemberRoleCommand command2 = new ChangeRelationMemberRoleCommand(testData.existingRelation, 8, "newRole");
+        assertTrue(command2.executeCommand());
+        assertFalse(testData.existingRelation.isModified());
+
+        command1.undoCommand();
+        command2.undoCommand();
+        assertFalse(testData.existingRelation.isModified());
+    }
+
+
+    /**
+     * Same role should be ignored.
+     */
+    @Test
+    public void testSameRole() {
+        // should be ignored
+        assertTrue(new ChangeRelationMemberRoleCommand(testData.existingRelation, 0, "node").executeCommand());
+        assertFalse(testData.existingRelation.isModified());
+    }
+
+    /**
+     * Test {@link ChangeRelationMemberRoleCommand#undoCommand()}.
+     */
+    @Test
+    public void testUndo() {
+        ChangeRelationMemberRoleCommand command = new ChangeRelationMemberRoleCommand(testData.existingRelation, 0, "newRole");
+        command.executeCommand();
+        assertEquals("newRole", testData.existingRelation.getMember(0).getRole());
+        assertTrue(testData.existingRelation.isModified());
+
+        command.undoCommand();
+        assertEquals("node", testData.existingRelation.getMember(0).getRole());
+        assertFalse(testData.existingRelation.isModified());
+
+        command.executeCommand();
+        assertEquals("newRole", testData.existingRelation.getMember(0).getRole());
+        assertTrue(testData.existingRelation.isModified());
+    }
+
+    /**
+     * Tests {@link ChangeCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     */
+    @Test
+    public void testFillModifiedData() {
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+        new ChangeRelationMemberRoleCommand(testData.existingRelation, 0, "newRole").fillModifiedData(modified, deleted, added);
+        assertArrayEquals(new Object[] {testData.existingRelation}, modified.toArray());
+        assertArrayEquals(new Object[] {}, deleted.toArray());
+        assertArrayEquals(new Object[] {}, added.toArray());
+    }
+
+    /**
+     * Test {@link ChangeRelationMemberRoleCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        testData.existingRelation.put("name", "xy");
+        assertTrue(new ChangeRelationMemberRoleCommand(testData.existingRelation, 0, "newRole").getDescriptionText()
+                .matches("Change relation member role for relation.*xy.*"));
+    }
+
+    /**
+     * Test {@link ChangeRelationMemberRoleCommand#getChildren()}
+     */
+    @Test
+    public void testChildren() {
+        assertNull(new ChangeRelationMemberRoleCommand(testData.existingRelation, 0, "newRole").getChildren());
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/command/CommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/CommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/CommandTest.java	(revision 10663)
@@ -2,11 +2,27 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.User;
+import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -18,9 +34,45 @@
 
     /**
-     * Setup test.
-     */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+     * We need prefs for nodes / data sets.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().i18n();
+    private CommandTestData testData;
+
+    /**
+     * Set up the test data.
+     */
+    @Before
+    public void createTestData() {
+        testData = new CommandTestData();
+    }
+
+    /**
+     * Test {@link Command#invalidBecauselayerRemoved(org.openstreetmap.josm.gui.layer.Layer)}
+     */
+    @Test
+    public void testInvalidBecauselayerRemoved() {
+        OsmDataLayer layer2 = new OsmDataLayer(new DataSet(), "test", null);
+
+        Command command = new NopCommand();
+        assertFalse(command.invalidBecauselayerRemoved(layer2));
+        assertTrue(command.invalidBecauselayerRemoved(testData.layer));
+
+        Command command2 = new NopCommand(layer2);
+        assertTrue(command2.invalidBecauselayerRemoved(layer2));
+        assertFalse(command2.invalidBecauselayerRemoved(testData.layer));
+    }
+
+    /**
+     * Test {@link Command#getLayer()}
+     */
+    @Test
+    public void testGetLayer() {
+        OsmDataLayer layer2 = new OsmDataLayer(new DataSet(), "test", null);
+        Command command = new NopCommand();
+        Command command2 = new NopCommand(layer2);
+        assertSame(testData.layer, command.getLayer());
+        assertSame(layer2, command2.getLayer());
     }
 
@@ -40,3 +92,123 @@
             .verify();
     }
+
+    private static final class NopCommand extends Command {
+        NopCommand() {
+            super();
+        }
+
+        NopCommand(OsmDataLayer layer) {
+            super(layer);
+        }
+
+        @Override
+        public String getDescriptionText() {
+            return "";
+        }
+
+        @Override
+        public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
+                Collection<OsmPrimitive> added) {
+            // nop
+        }
+    }
+
+    /**
+     * A change test data consisting of two nodes and a way.
+     * @author Michael Zangl
+     */
+    public static class CommandTestData {
+        /**
+         * A test layer
+         */
+        public final OsmDataLayer layer;
+        /**
+         * A test node
+         */
+        public final Node existingNode;
+        /**
+         * A second test node
+         */
+        public final Node existingNode2;
+        /**
+         * A test way
+         */
+        public final Way existingWay;
+
+        /**
+         * Creates the new test data and adds {@link #layer} to the layer manager.
+         */
+        public CommandTestData() {
+            layer = new OsmDataLayer(new DataSet(), "layer", null);
+            Main.getLayerManager().addLayer(layer);
+
+            existingNode = createNode(5);
+            existingNode2 = createNode(6);
+
+            existingWay = createWay(10, existingNode, existingNode2);
+        }
+
+        /**
+         * Create and add a new test node.
+         * @param id the id
+         * @return The node.
+         */
+        public Node createNode(long id) {
+            Node node = new Node();
+            node.setOsmId(id, 1);
+            node.setCoor(LatLon.ZERO);
+            node.put("existing", "existing");
+            layer.data.addPrimitive(node);
+            return node;
+        }
+
+        /**
+         * Create and add a new test way.
+         * @param id the id
+         * @param nodes The nodes
+         * @return The way.
+         */
+        public Way createWay(int id, Node...nodes) {
+            Way way = new Way();
+            way.setOsmId(id, 1);
+            way.setNodes(Arrays.asList(nodes));
+            way.put("existing", "existing");
+            layer.data.addPrimitive(way);
+            return way;
+        }
+
+        /**
+         * Create and add a new test relation.
+         * @param id the id
+         * @param members The members
+         * @return The relation.
+         */
+        public Relation createRelation(int id, RelationMember...members) {
+            Relation relation = new Relation(id, 1);
+            for (RelationMember member : members) {
+                relation.addMember(member);
+            }
+            relation.put("existing", "existing");
+            layer.data.addPrimitive(relation);
+            return relation;
+        }
+    }
+
+    /**
+     * A change test data consisting of two nodes, a way and a relation.
+     * @author Michael Zangl
+     */
+    public static class CommandTestDataWithRelation extends CommandTestData {
+        /**
+         * A test relation
+         */
+        public final Relation existingRelation;
+
+        /**
+         * Creates the new test data and adds {@link #layer} to the layer manager.
+         */
+        public CommandTestDataWithRelation() {
+            existingRelation = createRelation(20, new RelationMember("node", existingNode), new RelationMember("way", existingWay));
+        }
+    }
 }
Index: /trunk/test/unit/org/openstreetmap/josm/command/DeleteCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/DeleteCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/DeleteCommandTest.java	(revision 10663)
@@ -2,11 +2,29 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.command.CommandTest.CommandTestDataWithRelation;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.User;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.WaySegment;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -18,9 +36,338 @@
 
     /**
-     * Setup test.
-     */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+     * We need prefs for nodes.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().i18n();
+    private CommandTestDataWithRelation testData;
+
+    /**
+     * Set up the test data.
+     */
+    @Before
+    public void createTestData() {
+        testData = new CommandTestDataWithRelation();
+    }
+
+    /**
+     * A simple deletion test with no references
+     */
+    @Test
+    public void testSimpleDelete() {
+        Node node = testData.createNode(15);
+        assertTrue(testData.layer.data.allPrimitives().contains(node));
+
+        new DeleteCommand(node).executeCommand();
+
+        assertTrue(node.isDeleted());
+        assertTrue(node.isModified());
+        assertFalse(testData.layer.data.allNonDeletedPrimitives().contains(node));
+    }
+
+    /**
+     * A delete should not delete refered objects but should should remove the reference.
+     */
+    @Test
+    public void testDeleteIgnoresReferences() {
+        assertTrue(testData.existingNode.getReferrers().contains(testData.existingRelation));
+        new DeleteCommand(testData.existingRelation).executeCommand();
+
+        assertTrue(testData.existingRelation.isDeleted());
+        assertEquals(0, testData.existingRelation.getMembersCount());
+        assertFalse(testData.existingNode.isDeleted());
+        assertFalse(testData.existingWay.isDeleted());
+        assertFalse(testData.existingNode.getReferrers().contains(testData.existingRelation));
+
+        // same for the way
+        assertTrue(testData.existingNode.getReferrers().contains(testData.existingWay));
+        new DeleteCommand(testData.existingWay).executeCommand();
+        assertEquals(0, testData.existingWay.getNodesCount());
+        assertFalse(testData.existingNode.getReferrers().contains(testData.existingWay));
+    }
+
+    /**
+     * A delete should delete all objects with references to the deleted one
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testDeleteFailsOnDelted() {
+        new DeleteCommand(testData.existingRelation).executeCommand();
+
+        new DeleteCommand(testData.existingRelation).executeCommand();
+    }
+
+    /**
+     * A delete should delete all objects with references to the deleted one
+     */
+    @Test
+    public void testReferedDelete() {
+        DeleteCommand.deleteWithReferences(testData.layer, Arrays.asList(testData.existingNode), true).executeCommand();
+
+        assertTrue(testData.existingNode.isDeleted());
+        assertEquals(0, testData.existingWay.getNodesCount());
+        assertTrue(testData.existingWay.isDeleted());
+    }
+
+    /**
+     * Delete nodes that would be without reference afterwards.
+     */
+    @Test
+    public void testDelteNodesInWay() {
+        testData.existingNode.removeAll();
+        // That untagged node should be deleted.
+        testData.existingNode2.removeAll();
+        DeleteCommand.delete(testData.layer, Arrays.asList(testData.existingWay), true, true).executeCommand();
+
+        assertTrue(testData.existingWay.isDeleted());
+        assertTrue(testData.existingNode2.isDeleted());
+        assertFalse(testData.existingNode.isDeleted());
+        assertFalse(testData.existingRelation.isDeleted());
+
+        // Same test, now with tagged nodes
+        Node node1 = testData.createNode(15);
+        Node node2 = testData.createNode(16);
+        Node node3 = testData.createNode(17);
+        Node node4 = testData.createNode(18);
+        node2.removeAll();
+        node4.removeAll();
+        Way way1 = new Way(25, 1);
+        way1.setNodes(Arrays.asList(node1, node2, node3));
+        testData.layer.data.addPrimitive(way1);
+        Way way2 = new Way(26, 1);
+        way2.setNodes(Arrays.asList(node2, node3, node4));
+        testData.layer.data.addPrimitive(way2);
+        DeleteCommand.delete(testData.layer, Arrays.asList(way1, way2), true, true).executeCommand();
+
+        assertTrue(way1.isDeleted());
+        assertTrue(way2.isDeleted());
+        assertFalse(node1.isDeleted());
+        assertTrue(node2.isDeleted());
+        assertFalse(node3.isDeleted());
+        assertTrue(node4.isDeleted());
+    }
+
+    /**
+     * Test that {@link DeleteCommand} checks for non-null.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testConsistency() {
+        new DeleteCommand(Arrays.asList(testData.existingNode, testData.existingWay, null));
+    }
+
+    /**
+     * Test that {@link DeleteCommand} checks for the dataset
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testConsistencyDataset() {
+        testData.layer.data.removePrimitive(testData.existingNode);
+        new DeleteCommand(Arrays.asList(testData.existingNode, testData.existingWay));
+    }
+
+    /**
+     * Test that {@link DeleteCommand} checks for non-empty list
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testConsistencyNonEmpty() {
+        new DeleteCommand(Arrays.<OsmPrimitive>asList());
+    }
+
+    /**
+     * Test that {@link DeleteCommand} checks for non-null list
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testConsistencyNonNull() {
+        new DeleteCommand((Collection<OsmPrimitive>) null);
+    }
+
+    /**
+     * Test {@link DeleteCommand#undoCommand()}
+     */
+    @Test
+    public void testUndo() {
+        DeleteCommand command = new DeleteCommand(
+                Arrays.asList(testData.existingNode, testData.existingNode2, testData.existingWay));
+        command.executeCommand();
+
+        assertTrue(testData.existingNode.isDeleted());
+        assertTrue(testData.existingWay.isDeleted());
+
+        command.undoCommand();
+
+        assertFalse(testData.existingNode.isDeleted());
+        assertFalse(testData.existingWay.isDeleted());
+        assertEquals("existing", testData.existingNode.get("existing"));
+
+        command.executeCommand();
+
+        assertTrue(testData.existingNode.isDeleted());
+        assertTrue(testData.existingWay.isDeleted());
+    }
+
+    /**
+     * Test {@link DeleteCommand#deleteWaySegment(OsmDataLayer, org.openstreetmap.josm.data.osm.WaySegment)}
+     * Way with only 1 segment
+     */
+    @Test
+    public void testDeleteWaySegment() {
+        Way way1 = testData.createWay(100, testData.createNode(101), testData.createNode(102));
+        WaySegment ws = new WaySegment(way1, 0);
+        Command command = DeleteCommand.deleteWaySegment(testData.layer, ws);
+        command.executeCommand();
+
+        assertTrue(way1.isDeleted());
+    }
+
+    /**
+     * Test {@link DeleteCommand#deleteWaySegment(OsmDataLayer, org.openstreetmap.josm.data.osm.WaySegment)}
+     * Delete end of way
+     */
+    @Test
+    public void testDeleteWaySegmentEndOfWay() {
+        Way way = testData.createWay(200, testData.createNode(201), testData.createNode(202), testData.createNode(203),
+                testData.createNode(204));
+        WaySegment ws = new WaySegment(way, 2);
+        Command command = DeleteCommand.deleteWaySegment(testData.layer, ws);
+        command.executeCommand();
+
+        assertEquals(3, way.getNodesCount());
+        assertEquals(201, way.getNodeId(0));
+        assertEquals(202, way.getNodeId(1));
+        assertEquals(203, way.getNodeId(2));
+    }
+
+    /**
+     * Test {@link DeleteCommand#deleteWaySegment(OsmDataLayer, org.openstreetmap.josm.data.osm.WaySegment)}
+     * Delete start of way
+     */
+    @Test
+    public void testDeleteWaySegmentStartOfWay() {
+        Way way = testData.createWay(100, testData.createNode(101), testData.createNode(102), testData.createNode(103),
+                testData.createNode(104));
+        WaySegment ws = new WaySegment(way, 0);
+        Command command = DeleteCommand.deleteWaySegment(testData.layer, ws);
+        command.executeCommand();
+
+        assertEquals(3, way.getNodesCount());
+        assertEquals(102, way.getNodeId(0));
+        assertEquals(103, way.getNodeId(1));
+        assertEquals(104, way.getNodeId(2));
+    }
+
+    /**
+     * Test {@link DeleteCommand#deleteWaySegment(OsmDataLayer, org.openstreetmap.josm.data.osm.WaySegment)}
+     * Delete start of way
+     */
+    @Test
+    public void testDeleteWaySegmentSplit() {
+        Node node103 = testData.createNode(103);
+        Node node104 = testData.createNode(104);
+        Way way = testData.createWay(100, testData.createNode(101), testData.createNode(102), node103, node104);
+        WaySegment ws = new WaySegment(way, 1);
+        Command command = DeleteCommand.deleteWaySegment(testData.layer, ws);
+        command.executeCommand();
+
+        assertEquals(2, way.getNodesCount());
+        assertEquals(101, way.getNodeId(0));
+        assertEquals(102, way.getNodeId(1));
+        // there needs to be a new way
+        assertEquals(1, node104.getReferrers().size());
+        Way newWay = (Way) node104.getReferrers().get(0);
+        assertEquals(2, newWay.getNodesCount());
+        assertEquals(103, newWay.getNodeId(0));
+        assertEquals(104, newWay.getNodeId(1));
+    }
+
+    /**
+     * Test {@link DeleteCommand#deleteWaySegment(OsmDataLayer, org.openstreetmap.josm.data.osm.WaySegment)}
+     * Delete start of way
+     */
+    @Test
+    public void testDeleteWaySegmentCycle() {
+        Node n = testData.createNode(101);
+        Way way = testData.createWay(100, n, testData.createNode(102), testData.createNode(103),
+                testData.createNode(104), n);
+        WaySegment ws = new WaySegment(way, 2);
+        Command command = DeleteCommand.deleteWaySegment(testData.layer, ws);
+        command.executeCommand();
+
+        assertEquals(4, way.getNodesCount());
+        assertEquals(104, way.getNodeId(0));
+        assertEquals(101, way.getNodeId(1));
+        assertEquals(102, way.getNodeId(2));
+        assertEquals(103, way.getNodeId(3));
+    }
+
+    /**
+     * Tests {@link DeleteCommand#getChildren()}
+     */
+    @Test
+    public void testGetChildren() {
+        testData.existingNode.put("name", "xy");
+        Collection<PseudoCommand> children = new DeleteCommand(Arrays.<OsmPrimitive>asList(testData.existingNode, testData.existingNode2))
+                .getChildren();
+        assertEquals(2, children.size());
+        assertTrue(children.stream().allMatch(c -> c.getParticipatingPrimitives().size() == 1));
+        assertTrue(children.stream().anyMatch(c -> c.getParticipatingPrimitives().iterator().next() == testData.existingNode));
+        assertTrue(children.stream().anyMatch(c -> c.getParticipatingPrimitives().iterator().next() == testData.existingNode2));
+        assertTrue(children.stream().anyMatch(c -> c.getDescriptionText().matches("Deleted '.*xy.*'")));
+    }
+
+    /**
+     * Tests {@link DeleteCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     */
+    @Test
+    public void testFillModifiedData() {
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+        new DeleteCommand(Arrays.<OsmPrimitive>asList(testData.existingNode)).fillModifiedData(modified, deleted, added);
+        // intentionally left empty.
+        assertArrayEquals(new Object[] {}, modified.toArray());
+        assertArrayEquals(new Object[] {}, deleted.toArray());
+        assertArrayEquals(new Object[] {}, added.toArray());
+    }
+
+    /**
+     * Tests {@link DeleteCommand#getParticipatingPrimitives()}
+     */
+    @Test
+    public void testGetParticipatingPrimitives() {
+        DeleteCommand command = new DeleteCommand(Arrays.<OsmPrimitive>asList(testData.existingNode));
+        assertArrayEquals(new Object[] {testData.existingNode }, command.getParticipatingPrimitives().toArray());
+
+        DeleteCommand command2 = new DeleteCommand(
+                Arrays.<OsmPrimitive>asList(testData.existingNode, testData.existingWay));
+        assertArrayEquals(new Object[] {testData.existingNode, testData.existingWay},
+                command2.getParticipatingPrimitives().toArray());
+    }
+
+    /**
+     * Test {@link DeleteCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        Node node = testData.createNode(100);
+        node.put("name", "xy");
+        Way way = testData.createWay(101);
+        way.put("name", "xy");
+        Relation relation = testData.createRelation(102);
+        relation.put("name", "xy");
+
+        List<OsmPrimitive> nodeList = Arrays.<OsmPrimitive>asList(node);
+        assertTrue(new DeleteCommand(nodeList).getDescriptionText().matches("Delete node .*xy.*"));
+        List<OsmPrimitive> wayList = Arrays.<OsmPrimitive>asList(way);
+        assertTrue(new DeleteCommand(wayList).getDescriptionText().matches("Delete way .*xy.*"));
+        List<OsmPrimitive> relationList = Arrays.<OsmPrimitive>asList(relation);
+        assertTrue(new DeleteCommand(relationList).getDescriptionText().matches("Delete relation .*xy.*"));
+
+        List<OsmPrimitive> nodesList = Arrays.<OsmPrimitive>asList(node, testData.createNode(110));
+        assertTrue(new DeleteCommand(nodesList).getDescriptionText().matches("Delete 2 nodes"));
+        List<OsmPrimitive> waysList = Arrays.<OsmPrimitive>asList(way, testData.createWay(111));
+        assertTrue(new DeleteCommand(waysList).getDescriptionText().matches("Delete 2 ways"));
+        List<OsmPrimitive> relationsList = Arrays.<OsmPrimitive>asList(relation, testData.createRelation(112));
+        assertTrue(new DeleteCommand(relationsList).getDescriptionText().matches("Delete 2 relations"));
+
+        List<OsmPrimitive> mixed = Arrays.<OsmPrimitive>asList(node, way, relation);
+        assertTrue(new DeleteCommand(mixed).getDescriptionText().matches("Delete 3 objects"));
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/command/MoveCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/MoveCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/MoveCommandTest.java	(revision 10663)
@@ -2,12 +2,29 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.CommandTest.CommandTestDataWithRelation;
+import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -17,11 +34,223 @@
  */
 public class MoveCommandTest {
-
-    /**
-     * Setup test.
-     */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+    /**
+     * We need prefs for nodes.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().i18n().projection();
+    private CommandTestDataWithRelation testData;
+
+    /**
+     * Set up the test data.
+     */
+    @Before
+    public void createTestData() {
+        testData = new CommandTestDataWithRelation();
+    }
+
+    /**
+     * Test the various constructors.
+     */
+    @Test
+    public void testConstructors() {
+        EastNorth offset = new EastNorth(1, 2);
+        LatLon destLatLon = Main.getProjection().eastNorth2latlon(offset);
+        EastNorth start = new EastNorth(2, 0);
+
+        Set<OsmPrimitive> nodeAsCollection = Collections.<OsmPrimitive>singleton(testData.existingNode);
+        assertEquals(1, nodeAsCollection.size());
+        checkCommandAfterConstructor(new MoveCommand(nodeAsCollection, offset));
+        checkCommandAfterConstructor(new MoveCommand(testData.existingNode, destLatLon));
+        checkCommandAfterConstructor(new MoveCommand(nodeAsCollection, 1, 2));
+        checkCommandAfterConstructor(new MoveCommand(nodeAsCollection, start, start.add(offset)));
+        checkCommandAfterConstructor(new MoveCommand(testData.existingNode, 1, 2));
+        checkCommandAfterConstructor(new MoveCommand(testData.existingNode, start, start.add(offset)));
+    }
+
+    private void checkCommandAfterConstructor(MoveCommand moveCommand) {
+        ArrayList<OsmPrimitive> nodes = new ArrayList<>();
+        moveCommand.fillModifiedData(nodes, null, null);
+        assertEquals(nodes, new ArrayList<>(Collections.<OsmPrimitive>singleton(testData.existingNode)));
+
+        assertEquals("east", 1, moveCommand.getOffset().east(), 0.0001);
+        assertEquals("north", 2, moveCommand.getOffset().north(), 0.0001);
+    }
+
+    /**
+     * Test {@link MoveCommand#executeCommand()} for simple nodes.
+     */
+    @Test
+    public void testSingleMove() {
+        MoveCommand command = new MoveCommand(testData.existingNode, 1, 2);
+        testData.existingNode.setEastNorth(new EastNorth(3, 7));
+        command.executeCommand();
+        assertEquals("east", 4, testData.existingNode.getEastNorth().east(), 0.0001);
+        assertEquals("north", 9, testData.existingNode.getEastNorth().north(), 0.0001);
+    }
+
+    /**
+     * Test {@link MoveCommand#executeCommand()} for multiple nodes.
+     */
+    @Test
+    public void testMultipleMove() {
+        MoveCommand command = new MoveCommand(
+                Arrays.asList(testData.existingNode, testData.existingNode2, testData.existingWay),
+                new EastNorth(1, 2));
+
+        testData.existingNode.setEastNorth(new EastNorth(3, 7));
+        testData.existingNode2.setEastNorth(new EastNorth(4, 7));
+        command.executeCommand();
+
+        assertEquals("east", 4, testData.existingNode.getEastNorth().east(), 0.0001);
+        assertEquals("north", 9, testData.existingNode.getEastNorth().north(), 0.0001);
+        assertEquals("east", 5, testData.existingNode2.getEastNorth().east(), 0.0001);
+        assertEquals("north", 9, testData.existingNode2.getEastNorth().north(), 0.0001);
+    }
+
+    /**
+     * Test {@link MoveCommand#moveAgain(double, double)} and {@link MoveCommand#moveAgainTo(double, double)}.
+     */
+    @Test
+    public void testMoveAgain() {
+        MoveCommand command = new MoveCommand(testData.existingNode, 1, 2);
+        assertEquals("east", 1, command.getOffset().east(), 0.0001);
+        assertEquals("north", 2, command.getOffset().north(), 0.0001);
+
+        command.moveAgain(1, 2);
+        assertEquals("east", 2, command.getOffset().east(), 0.0001);
+        assertEquals("north", 4, command.getOffset().north(), 0.0001);
+
+        command.moveAgain(-9, -3);
+        assertEquals("east", -7, command.getOffset().east(), 0.0001);
+        assertEquals("north", 1, command.getOffset().north(), 0.0001);
+
+        command.moveAgainTo(1, 2);
+        assertEquals("east", 1, command.getOffset().east(), 0.0001);
+        assertEquals("north", 2, command.getOffset().north(), 0.0001);
+    }
+
+    /**
+     * Test {@link MoveCommand#saveCheckpoint()} and {@link MoveCommand#resetToCheckpoint()}
+     */
+    @Test
+    public void testCheckpoint() {
+        MoveCommand command = new MoveCommand(testData.existingNode, 2, 4);
+        assertEquals("east", 2, command.getOffset().east(), 0.0001);
+        assertEquals("north", 4, command.getOffset().north(), 0.0001);
+
+        command.saveCheckpoint();
+        command.moveAgain(3, 7);
+        assertEquals("east", 5, command.getOffset().east(), 0.0001);
+        assertEquals("north", 11, command.getOffset().north(), 0.0001);
+
+        command.resetToCheckpoint();
+        assertEquals("east", 2, command.getOffset().east(), 0.0001);
+        assertEquals("north", 4, command.getOffset().north(), 0.0001);
+    }
+
+    /**
+     * Test the start point mechanism.
+     */
+    @Test
+    public void testStartPoint() {
+        EastNorth start = new EastNorth(10, 20);
+        MoveCommand command = new MoveCommand(testData.existingNode, start, start.add(1, 2));
+        assertEquals("east", 1, command.getOffset().east(), 0.0001);
+        assertEquals("north", 2, command.getOffset().north(), 0.0001);
+
+        command.applyVectorTo(start.add(3, 4));
+        assertEquals("east", 3, command.getOffset().east(), 0.0001);
+        assertEquals("north", 4, command.getOffset().north(), 0.0001);
+
+        // set to 100, 200
+        command.changeStartPoint(new EastNorth(103, 204));
+        command.applyVectorTo(new EastNorth(101, 202));
+        assertEquals("east", 1, command.getOffset().east(), 0.0001);
+        assertEquals("north", 2, command.getOffset().north(), 0.0001);
+    }
+
+    /**
+     * Test the start point mechanism ignored.
+     */
+    @Test
+    public void testNoStartPoint() {
+        MoveCommand command = new MoveCommand(testData.existingNode, 1, 0);
+        // ignored
+        command.applyVectorTo(new EastNorth(3, 4));
+        assertEquals("east", 1, command.getOffset().east(), 0.0001);
+        assertEquals("north", 0, command.getOffset().north(), 0.0001);
+
+        // set to 100, 200
+        command.changeStartPoint(new EastNorth(101, 200));
+        // works
+        command.applyVectorTo(new EastNorth(101, 202));
+        assertEquals("east", 1, command.getOffset().east(), 0.0001);
+        assertEquals("north", 2, command.getOffset().north(), 0.0001);
+    }
+
+    /**
+     * Test {@link MoveCommand#undoCommand()}
+     */
+    @Test
+    public void testUndo() {
+        testData.existingNode.setEastNorth(new EastNorth(3, 7));
+        MoveCommand command = new MoveCommand(testData.existingNode, 1, 2);
+        command.executeCommand();
+        assertEquals("east", 4, testData.existingNode.getEastNorth().east(), 0.0001);
+        assertEquals("north", 9, testData.existingNode.getEastNorth().north(), 0.0001);
+
+        command.undoCommand();
+        assertEquals("east", 3, testData.existingNode.getEastNorth().east(), 0.0001);
+        assertEquals("north", 7, testData.existingNode.getEastNorth().north(), 0.0001);
+
+        command.executeCommand();
+        assertEquals("east", 4, testData.existingNode.getEastNorth().east(), 0.0001);
+        assertEquals("north", 9, testData.existingNode.getEastNorth().north(), 0.0001);
+    }
+
+    /**
+     * Tests {@link MoveCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     */
+    @Test
+    public void testFillModifiedData() {
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+        new MoveCommand(Arrays.<OsmPrimitive>asList(testData.existingNode), 1, 2).fillModifiedData(modified,
+                deleted, added);
+        assertArrayEquals(new Object[] {testData.existingNode }, modified.toArray());
+        assertArrayEquals(new Object[] {}, deleted.toArray());
+        assertArrayEquals(new Object[] {}, added.toArray());
+    }
+
+    /**
+     * Tests {@link MoveCommand#getParticipatingPrimitives()}
+     */
+    @Test
+    public void testGetParticipatingPrimitives() {
+        MoveCommand command = new MoveCommand(Arrays.<OsmPrimitive>asList(testData.existingNode), 1, 2);
+        command.executeCommand();
+        assertArrayEquals(new Object[] {testData.existingNode}, command.getParticipatingPrimitives().toArray());
+
+        MoveCommand command2 = new MoveCommand(
+                Arrays.<OsmPrimitive>asList(testData.existingNode, testData.existingWay), 1, 2);
+        command2.executeCommand();
+        assertArrayEquals(new Object[] {testData.existingNode, testData.existingNode2},
+                command2.getParticipatingPrimitives().toArray());
+    }
+
+    /**
+     * Test {@link MoveCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        Node node = new Node(LatLon.ZERO);
+        node.put("name", "xy");
+
+        List<OsmPrimitive> nodeList = Arrays.<OsmPrimitive>asList(node);
+        assertTrue(new MoveCommand(nodeList, 1, 2).getDescriptionText().matches("Move 1 node"));
+        List<OsmPrimitive> nodes = Arrays.<OsmPrimitive>asList(node, testData.existingNode, testData.existingNode2);
+        assertTrue(new MoveCommand(nodes, 1, 2).getDescriptionText().matches("Move 3 nodes"));
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/command/PurgeCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/PurgeCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/PurgeCommandTest.java	(revision 10663)
@@ -2,7 +2,19 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.command.CommandTest.CommandTestDataWithRelation;
 import org.openstreetmap.josm.data.conflict.Conflict;
 import org.openstreetmap.josm.data.osm.DataSet;
@@ -10,8 +22,12 @@
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.Storage;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -21,11 +37,105 @@
  */
 public class PurgeCommandTest {
+    /**
+     * We need prefs for nodes.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences();
+    private CommandTestDataWithRelation testData;
 
     /**
-     * Setup test.
+     * Set up the test data.
      */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+    @Before
+    public void createTestData() {
+        testData = new CommandTestDataWithRelation();
+    }
+
+    /**
+     * Test {@link PurgeCommand#executeCommand()}
+     */
+    @Test
+    public void testExecute() {
+        Relation relationParent = testData.createRelation(100, new RelationMember("child", testData.existingRelation));
+        Relation relationParent2 = testData.createRelation(101, new RelationMember("child", testData.existingRelation));
+        // to check that algorithm ignores it:
+        Relation relationParent3 = testData.createRelation(102, new RelationMember("child", testData.existingRelation));
+        PurgeCommand command = new PurgeCommand(testData.layer,
+                Arrays.<OsmPrimitive>asList(testData.existingNode, testData.existingNode2, testData.existingWay,
+                        testData.existingRelation, relationParent, relationParent2),
+                Arrays.<OsmPrimitive>asList(testData.existingNode2, testData.existingWay, testData.existingRelation));
+        command.executeCommand();
+        assertTrue(testData.existingNode2.isIncomplete());
+        assertTrue(testData.existingWay.isIncomplete());
+        assertTrue(testData.existingRelation.isIncomplete());
+        assertNull(relationParent.getDataSet());
+        assertNull(relationParent2.getDataSet());
+        assertNotNull(relationParent3.getDataSet());
+        assertFalse(relationParent3.isIncomplete());
+        assertNull(testData.existingNode.getDataSet());
+        assertFalse(testData.existingNode.isIncomplete());
+    }
+
+    /**
+     * Test {@link PurgeCommand#undoCommand()}
+     */
+    @Test
+    public void testUndo() {
+        PurgeCommand command = new PurgeCommand(testData.layer,
+                Arrays.<OsmPrimitive>asList(testData.existingNode, testData.existingWay),
+                Arrays.<OsmPrimitive>asList(testData.existingWay));
+        command.executeCommand();
+        assertTrue(testData.existingWay.isIncomplete());
+        assertNull(testData.existingNode.getDataSet());
+
+        command.undoCommand();
+        assertFalse(testData.existingWay.isIncomplete());
+        assertSame(testData.layer.data, testData.existingNode.getDataSet());
+
+        command.executeCommand();
+        assertTrue(testData.existingWay.isIncomplete());
+        assertNull(testData.existingNode.getDataSet());
+    }
+
+    /**
+     * Tests {@link PurgeCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     */
+    @Test
+    public void testFillModifiedData() {
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+        PurgeCommand command = new PurgeCommand(testData.layer, Arrays.<OsmPrimitive>asList(testData.existingNode),
+                Arrays.<OsmPrimitive>asList(testData.existingRelation));
+        command.fillModifiedData(modified, deleted, added);
+        // intentianally empty (?)
+        assertArrayEquals(new Object[] {}, modified.toArray());
+        assertArrayEquals(new Object[] {}, deleted.toArray());
+        assertArrayEquals(new Object[] {}, added.toArray());
+    }
+
+    /**
+     * Tests {@link PurgeCommand#getParticipatingPrimitives()}
+     */
+    @Test
+    public void testGetParticipatingPrimitives() {
+        PurgeCommand command = new PurgeCommand(testData.layer, Arrays.<OsmPrimitive>asList(testData.existingNode),
+                Arrays.<OsmPrimitive>asList(testData.existingRelation));
+        assertArrayEquals(new Object[] {testData.existingNode }, command.getParticipatingPrimitives().toArray());
+    }
+
+    /**
+     * Test {@link PurgeCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        List<OsmPrimitive> shortList = Arrays.<OsmPrimitive>asList(testData.existingWay);
+        assertTrue(new PurgeCommand(testData.layer, shortList, Arrays.<OsmPrimitive>asList()).getDescriptionText()
+                .matches("Purged 1 object"));
+        List<OsmPrimitive> longList = Arrays.<OsmPrimitive>asList(testData.existingNode, testData.existingNode2,
+                testData.existingWay);
+        assertTrue(new PurgeCommand(testData.layer, longList, Arrays.<OsmPrimitive>asList()).getDescriptionText()
+                .matches("Purged 3 objects"));
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/command/RemoveNodesCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/RemoveNodesCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/RemoveNodesCommandTest.java	(revision 10663)
@@ -2,12 +2,23 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.command.CommandTest.CommandTestDataWithRelation;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -19,9 +30,90 @@
 
     /**
-     * Setup test.
+     * We need prefs for nodes.
      */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences();
+    private CommandTestDataWithRelation testData;
+
+    /**
+     * Set up the test data.
+     */
+    @Before
+    public void createTestData() {
+        testData = new CommandTestDataWithRelation();
+    }
+
+    /**
+     * Test {@link RemoveNodesCommand#executeCommand()}
+     */
+    @Test
+    public void testExecute() {
+        RemoveNodesCommand command = new RemoveNodesCommand(testData.existingWay,
+                Collections.singletonList(testData.existingNode));
+
+        command.executeCommand();
+
+        assertFalse(testData.existingWay.containsNode(testData.existingNode));
+        assertTrue(testData.existingWay.containsNode(testData.existingNode2));
+        assertTrue(testData.existingWay.isModified());
+    }
+
+    /**
+     * Test {@link RemoveNodesCommand#undoCommand()}
+     */
+    @Test
+    public void testUndo() {
+        RemoveNodesCommand command = new RemoveNodesCommand(testData.existingWay,
+                Collections.singletonList(testData.existingNode));
+
+        command.executeCommand();
+
+        command.undoCommand();
+        assertTrue(testData.existingWay.containsNode(testData.existingNode));
+        assertTrue(testData.existingWay.containsNode(testData.existingNode2));
+        assertFalse(testData.existingWay.isModified());
+
+        command.executeCommand();
+
+        assertFalse(testData.existingWay.containsNode(testData.existingNode));
+        assertTrue(testData.existingWay.containsNode(testData.existingNode2));
+        assertTrue(testData.existingWay.isModified());
+    }
+
+    /**
+     * Tests {@link RemoveNodesCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     */
+    @Test
+    public void testFillModifiedData() {
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+        RemoveNodesCommand command = new RemoveNodesCommand(testData.existingWay,
+                Collections.singletonList(testData.existingNode));
+        command.fillModifiedData(modified, deleted, added);
+        assertArrayEquals(new Object[] {testData.existingWay }, modified.toArray());
+        assertArrayEquals(new Object[] {}, deleted.toArray());
+        assertArrayEquals(new Object[] {}, added.toArray());
+    }
+
+    /**
+     * Tests {@link RemoveNodesCommand#getParticipatingPrimitives()}
+     */
+    @Test
+    public void testGetParticipatingPrimitives() {
+        RemoveNodesCommand command = new RemoveNodesCommand(testData.existingWay,
+                Collections.singletonList(testData.existingNode));
+        command.executeCommand();
+        assertArrayEquals(new Object[] {testData.existingWay }, command.getParticipatingPrimitives().toArray());
+    }
+
+    /**
+     * Test {@link RemoveNodesCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        assertTrue(new RemoveNodesCommand(testData.existingWay, Collections.singletonList(testData.existingNode))
+                .getDescriptionText().matches("Removed nodes from .*"));
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/command/RotateCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/RotateCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/RotateCommandTest.java	(revision 10663)
@@ -2,12 +2,24 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.command.CommandTest.CommandTestData;
+import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -19,9 +31,100 @@
 
     /**
-     * Setup test.
+     * We need prefs for nodes.
      */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().projection();
+    private CommandTestData testData;
+
+    /**
+     * Set up the test data.
+     */
+    @Before
+    public void createTestData() {
+        testData = new CommandTestData();
+    }
+
+    /**
+     * Test a simple 45Â° rotation. Tests {@link RotateCommand#executeCommand()}
+     */
+    @Test
+    public void testRotate() {
+        // pivot needs to be at 0,0
+        Node n1 = new Node(new EastNorth(10, 10));
+        Node n2 = new Node(new EastNorth(-1, 0));
+        Node n3 = new Node(new EastNorth(-9, -10));
+        RotateCommand rotate = new RotateCommand(Arrays.asList(n1, n2, n3), new EastNorth(0, 0));
+        rotate.setRotationAngle(Math.PI / 4);
+        rotate.executeCommand();
+
+        assertEquals(Math.sqrt(2) * 10, n1.getEastNorth().east(), 0.0001);
+        assertEquals(0, n1.getEastNorth().north(), 0.0001);
+        assertEquals(-1 / Math.sqrt(2), n2.getEastNorth().east(), 0.0001);
+        assertEquals(1 / Math.sqrt(2), n2.getEastNorth().north(), 0.0001);
+    }
+
+    /**
+     * Test {@link RotateCommand#undoCommand()}
+     */
+    @Test
+    public void testUndo() {
+        Node n1 = new Node(new EastNorth(10, 10));
+        Node n2 = new Node(new EastNorth(-1, 0));
+        Node n3 = new Node(new EastNorth(-9, -10));
+        RotateCommand rotate = new RotateCommand(Arrays.asList(n1, n2, n3), new EastNorth(0, 0));
+        rotate.setRotationAngle(Math.PI / 4);
+        rotate.executeCommand();
+        rotate.undoCommand();
+
+        assertEquals(10, n1.getEastNorth().east(), 0.0001);
+        assertEquals(10, n1.getEastNorth().north(), 0.0001);
+        assertEquals(-1, n2.getEastNorth().east(), 0.0001);
+        assertEquals(0, n2.getEastNorth().north(), 0.0001);
+
+        rotate.executeCommand();
+
+        assertEquals(-1 / Math.sqrt(2), n2.getEastNorth().east(), 0.0001);
+        assertEquals(1 / Math.sqrt(2), n2.getEastNorth().north(), 0.0001);
+    }
+
+    /**
+     * Tests {@link RotateCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     */
+    @Test
+    public void testFillModifiedData() {
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+        RotateCommand command = new RotateCommand(Arrays.asList(testData.existingNode),
+                new EastNorth(0, 0));
+        // intentionally empty
+        command.fillModifiedData(modified, deleted, added);
+        assertArrayEquals(new Object[] {}, modified.toArray());
+        assertArrayEquals(new Object[] {}, deleted.toArray());
+        assertArrayEquals(new Object[] {}, added.toArray());
+    }
+
+    /**
+     * Tests {@link RotateCommand#getParticipatingPrimitives()}
+     */
+    @Test
+    public void testGetParticipatingPrimitives() {
+        RotateCommand command = new RotateCommand(Arrays.asList(testData.existingNode), new EastNorth(0, 0));
+        command.executeCommand();
+        assertArrayEquals(new Object[] {testData.existingNode}, command.getParticipatingPrimitives().toArray());
+    }
+
+    /**
+     * Test {@link RotateCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        assertEquals("Rotate 1 node",
+                new RotateCommand(Arrays.asList(testData.existingNode), new EastNorth(0, 0))
+                        .getDescriptionText());
+        assertEquals("Rotate 2 nodes",
+                new RotateCommand(Arrays.asList(testData.existingNode, testData.existingNode2), new EastNorth(0, 0))
+                        .getDescriptionText());
     }
 
@@ -32,14 +135,10 @@
     public void equalsContract() {
         EqualsVerifier.forClass(RotateCommand.class).usingGetClass()
-            .withPrefabValues(LatLon.class,
-                LatLon.ZERO, new LatLon(45, 45))
-            .withPrefabValues(DataSet.class,
-                new DataSet(), new DataSet())
-            .withPrefabValues(User.class,
-                    User.createOsmUser(1, "foo"), User.createOsmUser(2, "bar"))
-            .withPrefabValues(OsmDataLayer.class,
-                new OsmDataLayer(new DataSet(), "1", null), new OsmDataLayer(new DataSet(), "2", null))
-            .suppress(Warning.NONFINAL_FIELDS)
-            .verify();
+                .withPrefabValues(LatLon.class, LatLon.ZERO, new LatLon(45, 45))
+                .withPrefabValues(DataSet.class, new DataSet(), new DataSet())
+                .withPrefabValues(User.class, User.createOsmUser(1, "foo"), User.createOsmUser(2, "bar"))
+                .withPrefabValues(OsmDataLayer.class, new OsmDataLayer(new DataSet(), "1", null),
+                        new OsmDataLayer(new DataSet(), "2", null))
+                .suppress(Warning.NONFINAL_FIELDS).verify();
     }
 }
Index: /trunk/test/unit/org/openstreetmap/josm/command/ScaleCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/ScaleCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/ScaleCommandTest.java	(revision 10663)
@@ -2,12 +2,24 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.command.CommandTest.CommandTestData;
+import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -19,9 +31,100 @@
 
     /**
-     * Setup test.
+     * We need prefs for nodes.
      */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().projection();
+    private CommandTestData testData;
+
+    /**
+     * Set up the test data.
+     */
+    @Before
+    public void createTestData() {
+        testData = new CommandTestData();
+    }
+
+    /**
+     * Test a simple 2.5 scale. Tests {@link ScaleCommand#executeCommand()}
+     */
+    @Test
+    public void testScale() {
+        // pivot needs to be at 0,0
+        Node n1 = new Node(new EastNorth(10, 10));
+        Node n2 = new Node(new EastNorth(-1, 0));
+        Node n3 = new Node(new EastNorth(-9, -10));
+        ScaleCommand scale = new ScaleCommand(Arrays.asList(n1, n2, n3), new EastNorth(0, 0));
+        scale.setScalingFactor(2.5);
+        scale.executeCommand();
+
+        assertEquals(25, n1.getEastNorth().east(), 0.0001);
+        assertEquals(25, n1.getEastNorth().north(), 0.0001);
+        assertEquals(-2.5, n2.getEastNorth().east(), 0.0001);
+        assertEquals(0, n2.getEastNorth().north(), 0.0001);
+    }
+
+    /**
+     * Test {@link ScaleCommand#undoCommand()}
+     */
+    @Test
+    public void testUndo() {
+        Node n1 = new Node(new EastNorth(10, 10));
+        Node n2 = new Node(new EastNorth(-1, 0));
+        Node n3 = new Node(new EastNorth(-9, -10));
+        ScaleCommand scale = new ScaleCommand(Arrays.asList(n1, n2, n3), new EastNorth(0, 0));
+        scale.setScalingFactor(2.5);
+        scale.executeCommand();
+        scale.undoCommand();
+
+        assertEquals(10, n1.getEastNorth().east(), 0.0001);
+        assertEquals(10, n1.getEastNorth().north(), 0.0001);
+        assertEquals(-1, n2.getEastNorth().east(), 0.0001);
+        assertEquals(0, n2.getEastNorth().north(), 0.0001);
+
+        scale.executeCommand();
+
+        assertEquals(-2.5, n2.getEastNorth().east(), 0.0001);
+        assertEquals(0, n2.getEastNorth().north(), 0.0001);
+    }
+
+    /**
+     * Tests {@link ScaleCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     */
+    @Test
+    public void testFillModifiedData() {
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+        ScaleCommand command = new ScaleCommand(Arrays.asList(testData.existingNode),
+                new EastNorth(0, 0));
+        // intentionally empty
+        command.fillModifiedData(modified, deleted, added);
+        assertArrayEquals(new Object[] {}, modified.toArray());
+        assertArrayEquals(new Object[] {}, deleted.toArray());
+        assertArrayEquals(new Object[] {}, added.toArray());
+    }
+
+    /**
+     * Tests {@link ScaleCommand#getParticipatingPrimitives()}
+     */
+    @Test
+    public void testGetParticipatingPrimitives() {
+        ScaleCommand command = new ScaleCommand(Arrays.asList(testData.existingNode), new EastNorth(0, 0));
+        command.executeCommand();
+        assertArrayEquals(new Object[] {testData.existingNode }, command.getParticipatingPrimitives().toArray());
+    }
+
+    /**
+     * Test {@link ScaleCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        assertEquals("Scale 1 node",
+                new ScaleCommand(Arrays.asList(testData.existingNode), new EastNorth(0, 0))
+                        .getDescriptionText());
+        assertEquals("Scale 2 nodes",
+                new ScaleCommand(Arrays.asList(testData.existingNode, testData.existingNode2), new EastNorth(0, 0))
+                        .getDescriptionText());
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/command/SelectCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/SelectCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/SelectCommandTest.java	(revision 10663)
@@ -2,11 +2,23 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.command.CommandTest.CommandTestDataWithRelation;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -18,9 +30,115 @@
 
     /**
-     * Setup test.
+     * We need prefs for nodes.
      */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences();
+    private CommandTestDataWithRelation testData;
+
+    /**
+     * Set up the test data.
+     */
+    @Before
+    public void createTestData() {
+        testData = new CommandTestDataWithRelation();
+    }
+
+    /**
+     * Test {@link SelectCommand#executeCommand()}
+     */
+    @Test
+    public void testExecute() {
+        SelectCommand command = new SelectCommand(Arrays.asList(testData.existingNode, testData.existingWay));
+
+        testData.layer.data.setSelected(Arrays.asList(testData.existingNode2));
+
+        command.executeCommand();
+
+        assertTrue(testData.existingNode.isSelected());
+        assertFalse(testData.existingNode2.isSelected());
+        assertTrue(testData.existingWay.isSelected());
+    }
+
+    /**
+     * Test {@link SelectCommand#executeCommand()}
+     */
+    @Test
+    public void testExecuteAfterModify() {
+        List<OsmPrimitive> list = new ArrayList<>(Arrays.asList(testData.existingNode, testData.existingWay));
+        SelectCommand command = new SelectCommand(list);
+
+        list.remove(testData.existingNode);
+        list.add(testData.existingNode2);
+
+        command.executeCommand();
+
+        assertTrue(testData.existingNode.isSelected());
+        assertFalse(testData.existingNode2.isSelected());
+        assertTrue(testData.existingWay.isSelected());
+    }
+
+    /**
+     * Test {@link SelectCommand#undoCommand()}
+     */
+    @Test
+    public void testUndo() {
+        SelectCommand command = new SelectCommand(Arrays.asList(testData.existingNode, testData.existingWay));
+        testData.layer.data.setSelected(Arrays.asList(testData.existingNode2));
+
+        command.executeCommand();
+
+        command.undoCommand();
+
+        assertFalse(testData.existingNode.isSelected());
+        assertTrue(testData.existingNode2.isSelected());
+        assertFalse(testData.existingWay.isSelected());
+
+        command.executeCommand();
+
+        assertTrue(testData.existingNode.isSelected());
+        assertFalse(testData.existingNode2.isSelected());
+        assertTrue(testData.existingWay.isSelected());
+    }
+
+    /**
+     * Tests {@link SelectCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     */
+    @Test
+    public void testFillModifiedData() {
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+        SelectCommand command = new SelectCommand(Arrays.asList(testData.existingNode, testData.existingWay));
+        command.fillModifiedData(modified, deleted, added);
+        // intentionally empty.
+        assertArrayEquals(new Object[] {}, modified.toArray());
+        assertArrayEquals(new Object[] {}, deleted.toArray());
+        assertArrayEquals(new Object[] {}, added.toArray());
+    }
+
+    /**
+     * Tests {@link SelectCommand#getParticipatingPrimitives()}
+     */
+    @Test
+    public void testGetParticipatingPrimitives() {
+        SelectCommand command = new SelectCommand(Arrays.asList(testData.existingNode, testData.existingWay));
+        command.executeCommand();
+        assertArrayEquals(new Object[] {}, command.getParticipatingPrimitives().toArray());
+    }
+
+    /**
+     * Test {@link SelectCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        assertTrue(new SelectCommand(Arrays.<OsmPrimitive>asList(testData.existingNode))
+                .getDescriptionText().matches("Selected 1 object"));
+        assertTrue(new SelectCommand(Arrays.asList(testData.existingNode, testData.existingWay))
+                .getDescriptionText().matches("Selected 2 objects"));
+        assertTrue(new SelectCommand(Arrays.<OsmPrimitive>asList())
+                .getDescriptionText().matches("Selected 0 objects"));
+        assertTrue(new SelectCommand(null)
+                .getDescriptionText().matches("Selected 0 objects"));
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/command/SequenceCommandTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/command/SequenceCommandTest.java	(revision 10662)
+++ /trunk/test/unit/org/openstreetmap/josm/command/SequenceCommandTest.java	(revision 10663)
@@ -2,12 +2,27 @@
 package org.openstreetmap.josm.command;
 
-import org.junit.BeforeClass;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.command.CommandTest.CommandTestDataWithRelation;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import nl.jqno.equalsverifier.EqualsVerifier;
 import nl.jqno.equalsverifier.Warning;
@@ -19,9 +34,134 @@
 
     /**
-     * Setup test.
-     */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(false);
+     * We need prefs for nodes.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences();
+    private CommandTestDataWithRelation testData;
+
+    /**
+     * Set up the test data.
+     */
+    @Before
+    public void createTestData() {
+        testData = new CommandTestDataWithRelation();
+    }
+
+    /**
+     * Test {@link SequenceCommand#executeCommand()}
+     */
+    @Test
+    public void testExecute() {
+        final TestCommand command1 = new TestCommand(Arrays.<OsmPrimitive>asList(testData.existingNode));
+        TestCommand command2 = new TestCommand(Arrays.<OsmPrimitive>asList(testData.existingNode2)) {
+            @Override
+            public boolean executeCommand() {
+                assertTrue(command1.executed);
+                return super.executeCommand();
+            }
+        };
+        SequenceCommand command = new SequenceCommand("seq", Arrays.<Command>asList(command1, command2));
+
+        command.executeCommand();
+
+        assertTrue(command1.executed);
+        assertTrue(command2.executed);
+    }
+
+    /**
+     * Test {@link SequenceCommand#undoCommand()}
+     */
+    @Test
+    public void testUndo() {
+        final TestCommand command2 = new TestCommand(Arrays.<OsmPrimitive>asList(testData.existingNode2));
+        TestCommand command1 = new TestCommand(Arrays.<OsmPrimitive>asList(testData.existingNode)) {
+            @Override
+            public void undoCommand() {
+                assertFalse(command2.executed);
+                super.undoCommand();
+            }
+        };
+        SequenceCommand command = new SequenceCommand("seq", Arrays.<Command>asList(command1, command2));
+
+        command.executeCommand();
+
+        command.undoCommand();
+
+        assertFalse(command1.executed);
+        assertFalse(command2.executed);
+
+        command.executeCommand();
+
+        assertTrue(command1.executed);
+        assertTrue(command2.executed);
+    }
+
+    /**
+     * Test {@link SequenceCommand#undoCommand()}
+     */
+    @Test
+    public void testGetLastCommand() {
+        final TestCommand command1 = new TestCommand(Arrays.<OsmPrimitive>asList(testData.existingNode));
+        final TestCommand command2 = new TestCommand(Arrays.<OsmPrimitive>asList(testData.existingNode2));
+
+        assertEquals(command2, new SequenceCommand("seq", command1, command2).getLastCommand());
+        assertNull(new SequenceCommand("seq").getLastCommand());
+    }
+
+    /**
+     * Tests {@link SequenceCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
+     */
+    @Test
+    public void testFillModifiedData() {
+        Command command1 = new TestCommand(Arrays.<OsmPrimitive>asList(testData.existingNode));
+        Command command2 = new TestCommand(Arrays.<OsmPrimitive>asList(testData.existingNode2));
+        Command command3 = new TestCommand(Arrays.<OsmPrimitive>asList(testData.existingWay)) {
+            @Override
+            public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
+                    Collection<OsmPrimitive> added) {
+                deleted.addAll(primitives);
+            }
+        };
+        Command command4 = new TestCommand(Arrays.<OsmPrimitive>asList(testData.existingRelation)) {
+            @Override
+            public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
+                    Collection<OsmPrimitive> added) {
+                added.addAll(primitives);
+            }
+        };
+
+        ArrayList<OsmPrimitive> modified = new ArrayList<>();
+        ArrayList<OsmPrimitive> deleted = new ArrayList<>();
+        ArrayList<OsmPrimitive> added = new ArrayList<>();
+        SequenceCommand command = new SequenceCommand("seq", command1, command2, command3, command4);
+        command.fillModifiedData(modified, deleted, added);
+        assertArrayEquals(new Object[] {testData.existingNode, testData.existingNode2}, modified.toArray());
+        assertArrayEquals(new Object[] {testData.existingWay}, deleted.toArray());
+        assertArrayEquals(new Object[] {testData.existingRelation}, added.toArray());
+    }
+
+    /**
+     * Tests {@link SequenceCommand#getParticipatingPrimitives()}
+     */
+    @Test
+    public void testGetParticipatingPrimitives() {
+        Command command1 = new TestCommand(Arrays.<OsmPrimitive>asList(testData.existingNode));
+        Command command2 = new TestCommand(Arrays.<OsmPrimitive>asList(testData.existingNode2));
+
+        SequenceCommand command = new SequenceCommand("seq", command1, command2);
+        command.executeCommand();
+        Collection<? extends OsmPrimitive> primitives = command.getParticipatingPrimitives();
+        assertEquals(2, primitives.size());
+        assertTrue(primitives.contains(testData.existingNode));
+        assertTrue(primitives.contains(testData.existingNode2));
+    }
+
+    /**
+     * Test {@link SequenceCommand#getDescriptionText()}
+     */
+    @Test
+    public void testDescription() {
+        assertTrue(new SequenceCommand("test").getDescriptionText().matches("Sequence: test"));
     }
 
@@ -43,3 +183,49 @@
             .verify();
     }
+
+    private static class TestCommand extends Command {
+        protected final Collection<? extends OsmPrimitive> primitives;
+        protected boolean executed;
+
+        TestCommand(Collection<? extends OsmPrimitive> primitives) {
+            super();
+            this.primitives = primitives;
+        }
+
+        @Override
+        public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
+                Collection<OsmPrimitive> added) {
+            modified.addAll(primitives);
+        }
+
+        @Override
+        public String getDescriptionText() {
+            fail("Should not be called");
+            return "";
+        }
+
+        @Override
+        public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
+            return primitives;
+        }
+
+        @Override
+        public boolean executeCommand() {
+            assertFalse("Cannot execute twice", executed);
+            executed = true;
+            return true;
+        }
+
+        @Override
+        public void undoCommand() {
+            assertTrue("Cannot undo without execute", executed);
+            executed = false;
+        }
+
+        @Override
+        public String toString() {
+            return "TestCommand [primitives=" + primitives + "]";
+        }
+
+    }
 }
