Repository: missionpinball/mpf

Issue:
Better error for diverter without coil
Show a better error message: https://groups.google.com/forum/m/#!topic/mpf-users/YZlYmkEzAkw

Discussion:

Patch:
diff --git a/mpf/core/machine.py b/mpf/core/machine.py
index d40f23119..050a488cf 100644
--- a/mpf/core/machine.py
+++ b/mpf/core/machine.py
@@ -68,6 +68,7 @@ if MYPY:   # pragma: no cover
     from mpf.devices.dmd import Dmd
     from mpf.devices.rgb_dmd import RgbDmd
     from mpf.devices.flipper import Flipper
+    from mpf.devices.diverter import Diverter
 
 
 # pylint: disable-msg=too-many-instance-attributes
@@ -172,6 +173,7 @@ class MachineController(LogMixin):
             self.dmds = None                            # type: Dict[str, Dmd]
             self.rgb_dmds = None                        # type: Dict[str, RgbDmd]
             self.flippers = None                        # type: Dict[str, Flipper]
+            self.diverters = None                       # type: Dict[str, Diverter]
 
         self._set_machine_path()
 
diff --git a/mpf/devices/diverter.py b/mpf/devices/diverter.py
index 617f020d1..bee8182a0 100644
--- a/mpf/devices/diverter.py
+++ b/mpf/devices/diverter.py
@@ -168,14 +168,16 @@ class Diverter(SystemWideDevice):
 
     def _coil_activate(self):
         """Activate the coil."""
-        if self.config['type'] == 'pulse':
-            self.config['activation_coil'].pulse()
-        elif self.config['type'] == 'hold':
-            self.config['activation_coil'].enable()
+        if self.config['activation_coil']:
+            if self.config['type'] == 'pulse':
+                self.config['activation_coil'].pulse()
+            elif self.config['type'] == 'hold':
+                self.config['activation_coil'].enable()
 
     def _coil_deactivate(self):
         """Deactivate the coil."""
-        self.config['activation_coil'].disable()
+        if self.config['activation_coil']:
+            self.config['activation_coil'].disable()
 
         if self.config['deactivation_coil']:
             self.config['deactivation_coil'].pulse()
diff --git a/mpf/devices/stepper.py b/mpf/devices/stepper.py
index 29b5e8e60..c3b155a75 100644
--- a/mpf/devices/stepper.py
+++ b/mpf/devices/stepper.py
@@ -45,6 +45,9 @@ class Stepper(SystemWideDevice):
         yield from super()._initialize()
         self.platform = self.machine.get_platform_sections('stepper_controllers', self.config['platform'])
 
+        # first target is the reset position but we might get an early target during startup via events
+        self._target_position = self.config['reset_position']
+
         for position in self.config['named_positions']:
             self.machine.events.add_handler(self.config['named_positions'][position],
                                             self._position_event,
@@ -92,9 +95,9 @@ class Stepper(SystemWideDevice):
         self.debug_log("Homing stepper")
         yield from self._home()
 
-        # move to reset position
-        self.debug_log("Moving to reset position")
-        self.reset()
+        # run the loop at least once
+        self._is_moving.set()
+
         while True:
             # wait until we should be moving
             yield from self._is_moving.wait()
@@ -150,7 +153,7 @@ class Stepper(SystemWideDevice):
         self._is_homed = True
         self._is_moving.clear()
         # home position is 0
-        self._current_position = self._target_position = 0
+        self._current_position = 0
 
     def _post_ready_event(self):
         if not self._ball_search_started:


Test patch:
diff --git a/mpf/tests/machine_files/diverter/config/only_events_no_coils.yaml b/mpf/tests/machine_files/diverter/config/only_events_no_coils.yaml
new file mode 100644
index 000000000..ce86734cc
--- /dev/null
+++ b/mpf/tests/machine_files/diverter/config/only_events_no_coils.yaml
@@ -0,0 +1,25 @@
+#config_version=5
+
+config:
+- config.yaml
+
+diverters:
+    d_test_with_events:
+        debug: true
+        feeder_devices: test_trough
+        targets_when_active: playfield
+        targets_when_inactive: test_target
+
+servos:
+    s_diverter:
+        number:
+        positions:
+            0.7: diverter_d_test_with_events_activating
+            0.2: diverter_d_test_with_events_deactivating
+
+steppers:
+    s_diverter:
+        number:
+        named_positions:
+            20: diverter_d_test_with_events_activating
+            400: diverter_d_test_with_events_deactivating
diff --git a/mpf/tests/machine_files/diverter/config/test_hold_activation_time.yaml b/mpf/tests/machine_files/diverter/config/test_hold_activation_time.yaml
index 2b91e9eaf..a0d476155 100644
--- a/mpf/tests/machine_files/diverter/config/test_hold_activation_time.yaml
+++ b/mpf/tests/machine_files/diverter/config/test_hold_activation_time.yaml
@@ -12,4 +12,4 @@ diverters:
         targets_when_active: playfield
         targets_when_inactive: test_target
         activation_time: 4s
-        debug: True
\ No newline at end of file
+        debug: True
diff --git a/mpf/tests/test_Diverter.py b/mpf/tests/test_Diverter.py
index 55510f120..c48723360 100644
--- a/mpf/tests/test_Diverter.py
+++ b/mpf/tests/test_Diverter.py
@@ -1,12 +1,9 @@
-from mpf.tests.MpfTestCase import MpfTestCase
+from mpf.tests.MpfTestCase import MpfTestCase, test_config
 from unittest.mock import MagicMock
 
 
 class TestDiverter(MpfTestCase):
 
-    def getConfigFile(self):
-        return self._testMethodName + ".yaml"
-
     def getMachinePath(self):
         return 'tests/machine_files/diverter/'
 
@@ -25,19 +22,69 @@ class TestDiverter(MpfTestCase):
         self.queue = queue
         queue.wait()
 
+    @test_config("only_events_no_coils.yaml")
+    def test_diverter_with_servo_and_stepper(self):
+        self.queue = None
+        diverter = self.machine.diverters["d_test_with_events"]
+        self.advance_time_and_run(.1)
+
+        self.assertEqual(.2, self.machine.servos["s_diverter"].hw_servo.current_position)
+        self.assertEqual(400, self.machine.steppers["s_diverter"].hw_stepper._current_position)
+
+
+        self.assertFalse(diverter.enabled)
+        self.assertFalse(diverter.active)
+
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_trough"]
+        self.machine.playfield.add_ball()
+
+        self.advance_time_and_run(1)
+
+        self.assertTrue(diverter.enabled)
+        self.assertTrue(diverter.active)
+        self.assertEqual(.7, self.machine.servos["s_diverter"].hw_servo.current_position)
+        self.assertEqual(20, self.machine.steppers["s_diverter"].hw_stepper._current_position)
+
+        self.hit_and_release_switch("s_playfield")
+        self.machine_run()
+        self.assertFalse(diverter.active)
+
+        self.assertEqual(.2, self.machine.servos["s_diverter"].hw_servo.current_position)
+        self.assertEqual(400, self.machine.steppers["s_diverter"].hw_stepper._current_position)
+
+        self.hit_switch_and_run("s_ball_switch1", 1)
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_target"]
+        self.machine.playfield.add_ball()
+
+        self.advance_time_and_run(3)
+        self.assertFalse(diverter.enabled)
+        self.assertFalse(diverter.active)
+
+        self.hit_and_release_switch("s_diverter")
+        self.advance_time_and_run(0.5)
+        self.assertFalse(diverter.enabled)
+        self.assertFalse(diverter.active)
+
+        self.assertEqual(.2, self.machine.servos["s_diverter"].hw_servo.current_position)
+        self.assertEqual(400, self.machine.steppers["s_diverter"].hw_stepper._current_position)
+
+        self.advance_time_and_run(4)
+        self.assertEqual(0, diverter.diverting_ejects_count)
+
+    @test_config("test_delayed_eject.yaml")
     def test_delayed_eject(self):
         self.queue = None
-        diverter = self.machine.diverters.d_test_delayed_eject
+        diverter = self.machine.diverters["d_test_delayed_eject"]
 
-        self.machine.coils.c_diverter.enable = MagicMock()
-        self.machine.coils.c_diverter.disable = MagicMock()
+        self.machine.coils["c_diverter"].enable = MagicMock()
+        self.machine.coils["c_diverter"].disable = MagicMock()
 
         self.assertFalse(diverter.enabled)
         self.assertFalse(diverter.active)
 
         self.machine.events.add_handler("balldevice_test_trough_ball_eject_attempt", self._block_device)
 
-        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices.test_trough
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_trough"]
         self.machine.playfield.add_ball()
 
         self.advance_time_and_run(20)
@@ -48,20 +95,20 @@ class TestDiverter(MpfTestCase):
 
         self.assertTrue(diverter.enabled)
         self.assertTrue(diverter.active)
-        self.machine.coils.c_diverter.enable.assert_called_once_with()
-        self.machine.coils.c_diverter.enable = MagicMock()
-        assert not self.machine.coils.c_diverter.disable.called
+        self.machine.coils["c_diverter"].enable.assert_called_once_with()
+        self.machine.coils["c_diverter"].enable = MagicMock()
+        assert not self.machine.coils["c_diverter"].disable.called
 
         self.advance_time_and_run(4)
-        self.machine.coils.c_diverter.disable.assert_called_once_with()
-        assert not self.machine.coils.c_diverter.enable.called
+        self.machine.coils["c_diverter"].disable.assert_called_once_with()
+        assert not self.machine.coils["c_diverter"].enable.called
 
         self.hit_and_release_switch("s_playfield")
         self.machine_run()
         self.assertFalse(diverter.active)
 
         self.hit_switch_and_run("s_ball_switch1", 1)
-        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices.test_target
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_target"]
         self.machine.playfield.add_ball()
 
         self.advance_time_and_run(3)
@@ -74,19 +121,20 @@ class TestDiverter(MpfTestCase):
         self.assertFalse(diverter.active)
 
         self.advance_time_and_run(4)
-        assert not self.machine.coils.c_diverter.enable.called
+        assert not self.machine.coils["c_diverter"].enable.called
         self.assertEqual(0, diverter.diverting_ejects_count)
 
+    @test_config("test_hold_activation_time.yaml")
     def test_hold_activation_time(self):
-        diverter = self.machine.diverters.d_test_hold_activation_time
+        diverter = self.machine.diverters["d_test_hold_activation_time"]
 
-        self.machine.coils.c_diverter.enable = MagicMock()
-        self.machine.coils.c_diverter.disable = MagicMock()
+        self.machine.coils["c_diverter"].enable = MagicMock()
+        self.machine.coils["c_diverter"].disable = MagicMock()
 
         self.assertFalse(diverter.enabled)
         self.assertFalse(diverter.active)
 
-        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices.test_trough
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_trough"]
         self.machine.playfield.add_ball()
 
         self.advance_time_and_run(1)
@@ -97,20 +145,20 @@ class TestDiverter(MpfTestCase):
         self.advance_time_and_run(0.5)
         self.assertTrue(diverter.enabled)
         self.assertTrue(diverter.active)
-        self.machine.coils.c_diverter.enable.assert_called_once_with()
-        self.machine.coils.c_diverter.enable = MagicMock()
-        assert not self.machine.coils.c_diverter.disable.called
+        self.machine.coils["c_diverter"].enable.assert_called_once_with()
+        self.machine.coils["c_diverter"].enable = MagicMock()
+        assert not self.machine.coils["c_diverter"].disable.called
 
         self.advance_time_and_run(4)
-        self.machine.coils.c_diverter.disable.assert_called_once_with()
-        assert not self.machine.coils.c_diverter.enable.called
+        self.machine.coils["c_diverter"].disable.assert_called_once_with()
+        assert not self.machine.coils["c_diverter"].enable.called
 
         self.hit_and_release_switch("s_playfield")
         self.machine_run()
         self.assertFalse(diverter.active)
 
         self.hit_switch_and_run("s_ball_switch1", 1)
-        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices.test_target
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_target"]
         self.machine.playfield.add_ball()
 
         self.advance_time_and_run(3)
@@ -123,22 +171,23 @@ class TestDiverter(MpfTestCase):
         self.assertFalse(diverter.active)
 
         self.advance_time_and_run(4)
-        assert not self.machine.coils.c_diverter.enable.called
+        assert not self.machine.coils["c_diverter"].enable.called
 
+    @test_config("test_hold_no_activation_time.yaml")
     def test_hold_no_activation_time(self):
-        diverter = self.machine.diverters.d_test_hold
+        diverter = self.machine.diverters["d_test_hold"]
 
-        self.assertEqual("idle", self.machine.ball_devices.test_trough._state)
-        self.assertEqual("idle", self.machine.ball_devices.test_target._state)
+        self.assertEqual("idle", self.machine.ball_devices["test_trough"]._state)
+        self.assertEqual("idle", self.machine.ball_devices["test_target"]._state)
 
-        self.machine.coils.c_diverter.enable = MagicMock()
-        self.machine.coils.c_diverter.disable = MagicMock()
+        self.machine.coils["c_diverter"].enable = MagicMock()
+        self.machine.coils["c_diverter"].disable = MagicMock()
 
         self.assertFalse(diverter.enabled)
         self.assertFalse(diverter.active)
 
         # test active side
-        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices.test_trough
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_trough"]
         self.machine.playfield.add_ball()
 
         self.advance_time_and_run(1)
@@ -149,21 +198,21 @@ class TestDiverter(MpfTestCase):
         self.advance_time_and_run(0.5)
         self.assertTrue(diverter.enabled)
         self.assertTrue(diverter.active)
-        self.machine.coils.c_diverter.enable.assert_called_once_with()
-        self.machine.coils.c_diverter.enable = MagicMock()
-        assert not self.machine.coils.c_diverter.disable.called
+        self.machine.coils["c_diverter"].enable.assert_called_once_with()
+        self.machine.coils["c_diverter"].enable = MagicMock()
+        assert not self.machine.coils["c_diverter"].disable.called
 
         self.advance_time_and_run(4)
-        assert not self.machine.coils.c_diverter.disable.called
+        assert not self.machine.coils["c_diverter"].disable.called
 
         self.hit_and_release_switch("s_playfield")
         self.machine_run()
         self.assertFalse(diverter.active)
-        self.machine.coils.c_diverter.disable.assert_called_once_with()
+        self.machine.coils["c_diverter"].disable.assert_called_once_with()
 
         self.hit_switch_and_run("s_ball_switch1", 1)
         # test inactive side
-        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices.test_target
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_target"]
         self.machine.playfield.add_ball()
 
         self.advance_time_and_run(3)
@@ -176,14 +225,15 @@ class TestDiverter(MpfTestCase):
         self.assertFalse(diverter.active)
 
         self.advance_time_and_run(4)
-        assert not self.machine.coils.c_diverter.enable.called
+        assert not self.machine.coils["c_diverter"].enable.called
 
         self.hit_switch_and_run("s_ball_switch1", 1)
 
+    @test_config("test_missing_ball_at_source.yaml")
     def test_missing_ball_at_source(self):
-        diverter = self.machine.diverters.d_test
-        trough1 = self.machine.ball_devices.test_trough
-        target = self.machine.ball_devices.test_target
+        diverter = self.machine.diverters["d_test"]
+        trough1 = self.machine.ball_devices["test_trough"]
+        target = self.machine.ball_devices["test_target"]
 
         self.machine.default_platform.actions[trough1].set_result("missing")
         trough1.eject(1, target)
@@ -194,12 +244,13 @@ class TestDiverter(MpfTestCase):
 
         self.assertEqual(0, diverter.diverting_ejects_count)
 
+    @test_config("test_eject_to_oposide_sides2.yaml")
     def test_eject_to_oposide_sides2(self):
-        diverter = self.machine.diverters.d_test_hold
-        trough1 = self.machine.ball_devices.test_trough
-        trough2 = self.machine.ball_devices.test_trough2
+        diverter = self.machine.diverters["d_test_hold"]
+        trough1 = self.machine.ball_devices["test_trough"]
+        trough2 = self.machine.ball_devices["test_trough2"]
         playfield = self.machine.playfield
-        target = self.machine.ball_devices.test_target
+        target = self.machine.ball_devices["test_target"]
 
         self.assertEqual(3, trough1.balls)
         self.assertEqual(3, trough2.balls)
@@ -223,18 +274,19 @@ class TestDiverter(MpfTestCase):
         self.assertEqual(0, trough1.balls)
         self.assertEqual(0, trough2.balls)
 
+    @test_config("test_eject_to_oposide_sides.yaml")
     def test_eject_to_oposide_sides(self):
-        diverter = self.machine.diverters.d_test_hold
-        trough1 = self.machine.ball_devices.test_trough
-        trough2 = self.machine.ball_devices.test_trough2
+        diverter = self.machine.diverters["d_test_hold"]
+        trough1 = self.machine.ball_devices["test_trough"]
+        trough2 = self.machine.ball_devices["test_trough2"]
         playfield = self.machine.playfield
-        target = self.machine.ball_devices.test_target
+        target = self.machine.ball_devices["test_target"]
 
-        pulse1 = self.machine.coils.eject_coil1.pulse
-        pulse3 = self.machine.coils.eject_coil3.pulse
+        pulse1 = self.machine.coils["eject_coil1"].pulse
+        pulse3 = self.machine.coils["eject_coil3"].pulse
 
-        self.machine.coils.eject_coil1.pulse = MagicMock(wraps=pulse1)
-        self.machine.coils.eject_coil3.pulse = MagicMock(wraps=pulse3)
+        self.machine.coils["eject_coil1"].pulse = MagicMock(wraps=pulse1)
+        self.machine.coils["eject_coil3"].pulse = MagicMock(wraps=pulse3)
 
         # this goes to the active side of the diverter
         trough1.eject(1, playfield)
@@ -250,25 +302,25 @@ class TestDiverter(MpfTestCase):
         self.assertTrue(diverter.active)
 
         # only trough1 ejects. trought2 waits because of diverter
-        self.assertTrue(self.machine.coils.eject_coil1.pulse.called)
-        assert not self.machine.coils.eject_coil3.pulse.called
+        self.assertTrue(self.machine.coils["eject_coil1"].pulse.called)
+        assert not self.machine.coils["eject_coil3"].pulse.called
         self.assertEqual(1, diverter.diverting_ejects_count)
 
         self.hit_and_release_switch("s_playfield")
         self.advance_time_and_run(3)
         # wait for cooldown
-        self.assertFalse(self.machine.coils.eject_coil3.pulse.called)
+        self.assertFalse(self.machine.coils["eject_coil3"].pulse.called)
         self.assertEqual(1, diverter.diverting_ejects_count)
         self.advance_time_and_run(3)
-        self.assertTrue(self.machine.coils.eject_coil3.pulse.called)
+        self.assertTrue(self.machine.coils["eject_coil3"].pulse.called)
         self.assertEqual(1, diverter.diverting_ejects_count)
         self.assertFalse(diverter.enabled)
         self.assertFalse(diverter.active)
 
-        self.machine.coils.eject_coil1.pulse = MagicMock(wraps=pulse1)
-        self.machine.coils.eject_coil3.pulse = MagicMock(wraps=pulse3)
+        self.machine.coils["eject_coil1"].pulse = MagicMock(wraps=pulse1)
+        self.machine.coils["eject_coil3"].pulse = MagicMock(wraps=pulse3)
 
-        self.machine.ball_devices.test_target.eject()
+        self.machine.ball_devices["test_target"].eject()
         self.advance_time_and_run(20)
 
         self.assertEqual("idle", trough1._state)
@@ -293,8 +345,8 @@ class TestDiverter(MpfTestCase):
         self.assertFalse(diverter.enabled)
         self.assertFalse(diverter.active)
 
-        self.assertTrue(self.machine.coils.eject_coil3.pulse.called)
-        assert not self.machine.coils.eject_coil1.pulse.called
+        self.assertTrue(self.machine.coils["eject_coil3"].pulse.called)
+        assert not self.machine.coils["eject_coil1"].pulse.called
 
         self.hit_and_release_switch("s_playfield")
         self.advance_time_and_run(3)
@@ -307,52 +359,53 @@ class TestDiverter(MpfTestCase):
         self.assertTrue(diverter.enabled)
         self.assertTrue(diverter.active)
 
-        self.assertTrue(self.machine.coils.eject_coil1.pulse.called)
+        self.assertTrue(self.machine.coils["eject_coil1"].pulse.called)
         self.advance_time_and_run(20)
 
         self.assertEqual(0, diverter.diverting_ejects_count)
 
+    @test_config("test_pulsed_activation_time.yaml")
     def test_pulsed_activation_time(self):
-        diverter = self.machine.diverters.d_test_pulse
+        diverter = self.machine.diverters["d_test_pulse"]
 
-        self.machine.coils.c_diverter.pulse = MagicMock()
-        self.machine.coils.c_diverter_disable.pulse = MagicMock()
+        self.machine.coils["c_diverter"].pulse = MagicMock()
+        self.machine.coils["c_diverter_disable"].pulse = MagicMock()
 
         self.post_event("machine_reset_phase_3")
         self.assertFalse(diverter.enabled)
         self.assertFalse(diverter.active)
-        self.assertTrue(self.machine.coils.c_diverter_disable.pulse.called)
-        assert not self.machine.coils.c_diverter.pulse.called
+        self.assertTrue(self.machine.coils["c_diverter_disable"].pulse.called)
+        assert not self.machine.coils["c_diverter"].pulse.called
 
-        self.assertEqual("idle", self.machine.ball_devices.test_trough._state)
-        self.assertEqual("idle", self.machine.ball_devices.test_target._state)
+        self.assertEqual("idle", self.machine.ball_devices["test_trough"]._state)
+        self.assertEqual("idle", self.machine.ball_devices["test_target"]._state)
 
-        self.machine.coils.c_diverter.pulse = MagicMock()
-        self.machine.coils.c_diverter_disable.pulse = MagicMock()
+        self.machine.coils["c_diverter"].pulse = MagicMock()
+        self.machine.coils["c_diverter_disable"].pulse = MagicMock()
 
         self.assertFalse(diverter.enabled)
         self.assertFalse(diverter.active)
 
-        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices.test_trough
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_trough"]
         self.machine.playfield.add_ball()
 
         self.advance_time_and_run(1)
         self.assertTrue(diverter.enabled)
         self.assertTrue(diverter.active)
-        self.assertTrue(self.machine.coils.c_diverter.pulse.called)
-        self.machine.coils.c_diverter.pulse = MagicMock()
-        assert not self.machine.coils.c_diverter_disable.pulse.called
+        self.assertTrue(self.machine.coils["c_diverter"].pulse.called)
+        self.machine.coils["c_diverter"].pulse = MagicMock()
+        assert not self.machine.coils["c_diverter_disable"].pulse.called
 
         self.advance_time_and_run(4)
-        assert not self.machine.coils.c_diverter_disable.pulse.called
+        assert not self.machine.coils["c_diverter_disable"].pulse.called
 
         self.hit_and_release_switch("s_playfield")
         self.machine_run()
         self.assertFalse(diverter.active)
-        self.assertTrue(self.machine.coils.c_diverter_disable.pulse.called)
+        self.assertTrue(self.machine.coils["c_diverter_disable"].pulse.called)
 
         self.hit_switch_and_run("s_ball_switch1", 1)
-        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices.test_target
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_target"]
         self.machine.playfield.add_ball()
 
         self.advance_time_and_run(3)
@@ -365,11 +418,12 @@ class TestDiverter(MpfTestCase):
         self.assertFalse(diverter.active)
 
         self.advance_time_and_run(4)
-        assert not self.machine.coils.c_diverter.pulse.called
+        assert not self.machine.coils["c_diverter"].pulse.called
         self.assertEqual(0, diverter.diverting_ejects_count)
 
+    @test_config("test_diverter_with_switch.yaml")
     def test_diverter_with_switch(self):
-        diverter = self.machine.diverters.d_test
+        diverter = self.machine.diverters["d_test"]
 
         self.assertFalse(diverter.enabled)
         self.assertFalse(diverter.active)
@@ -417,8 +471,9 @@ class TestDiverter(MpfTestCase):
         self.assertFalse(diverter.enabled)
         self.assertFalse(diverter.active)
 
+    @test_config("test_diverter_auto_disable.yaml")
     def test_diverter_auto_disable(self):
-        diverter = self.machine.diverters.d_test
+        diverter = self.machine.diverters["d_test"]
 
         # enable diverter
         diverter.enable()
@@ -435,16 +490,17 @@ class TestDiverter(MpfTestCase):
         self.assertFalse(diverter.enabled)
         self.assertFalse(diverter.active)
 
+    @test_config("test_activation_switch_and_eject_confirm_switch.yaml")
     def test_activation_switch_and_eject_confirm_switch(self):
-        diverter = self.machine.diverters.d_test_hold_activation_time
+        diverter = self.machine.diverters["d_test_hold_activation_time"]
 
-        self.machine.coils.c_diverter.enable = MagicMock()
-        self.machine.coils.c_diverter.disable = MagicMock()
+        self.machine.coils["c_diverter"].enable = MagicMock()
+        self.machine.coils["c_diverter"].disable = MagicMock()
 
         self.assertFalse(diverter.enabled)
         self.assertFalse(diverter.active)
 
-        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices.test_trough2
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_trough2"]
         self.machine.playfield.add_ball()
 
         self.advance_time_and_run(.01)
@@ -455,21 +511,21 @@ class TestDiverter(MpfTestCase):
         self.advance_time_and_run(3)
         self.assertTrue(diverter.enabled)
         self.assertTrue(diverter.active)
-        self.machine.coils.c_diverter.enable.assert_called_once_with()
-        self.machine.coils.c_diverter.enable = MagicMock()
-        assert not self.machine.coils.c_diverter.disable.called
+        self.machine.coils["c_diverter"].enable.assert_called_once_with()
+        self.machine.coils["c_diverter"].enable = MagicMock()
+        assert not self.machine.coils["c_diverter"].disable.called
 
         self.advance_time_and_run(4)
-        self.machine.coils.c_diverter.disable.assert_called_once_with()
-        assert not self.machine.coils.c_diverter.enable.called
+        self.machine.coils["c_diverter"].disable.assert_called_once_with()
+        assert not self.machine.coils["c_diverter"].enable.called
 
         self.hit_and_release_switch("s_playfield")
         self.machine_run()
         self.assertFalse(diverter.active)
 
         self.hit_switch_and_run("s_ball_switch1", 1)
-        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices.test_target
-        self.machine.ball_devices.test_trough2.eject(1, self.machine.ball_devices.test_target)
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_target"]
+        self.machine.ball_devices["test_trough2"].eject(1, self.machine.ball_devices["test_target"])
 
         self.advance_time_and_run(.01)
         self.assertFalse(diverter.enabled)
@@ -481,24 +537,25 @@ class TestDiverter(MpfTestCase):
         self.assertFalse(diverter.active)
 
         self.advance_time_and_run(4)
-        assert not self.machine.coils.c_diverter.enable.called
+        assert not self.machine.coils["c_diverter"].enable.called
         self.assertEqual(0, diverter.diverting_ejects_count)
 
+    @test_config("test_diverter_dual_wound_coil.yaml")
     def test_diverter_dual_wound_coil(self):
-        diverter = self.machine.diverters.d_test_dual_wound
+        diverter = self.machine.diverters["d_test_dual_wound"]
 
-        self.assertEqual("idle", self.machine.ball_devices.test_trough._state)
-        self.assertEqual("idle", self.machine.ball_devices.test_target._state)
+        self.assertEqual("idle", self.machine.ball_devices["test_trough"]._state)
+        self.assertEqual("idle", self.machine.ball_devices["test_target"]._state)
 
-        self.machine.coils.c_hold.enable = MagicMock()
-        self.machine.coils.c_hold.disable = MagicMock()
-        self.machine.coils.c_power.pulse = MagicMock()
+        self.machine.coils["c_hold"].enable = MagicMock()
+        self.machine.coils["c_hold"].disable = MagicMock()
+        self.machine.coils["c_power"].pulse = MagicMock()
 
         self.assertFalse(diverter.enabled)
         self.assertFalse(diverter.active)
 
         # test active side
-        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices.test_trough
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_trough"]
         self.machine.playfield.add_ball()
 
         self.advance_time_and_run(1)
@@ -509,23 +566,23 @@ class TestDiverter(MpfTestCase):
         self.advance_time_and_run(0.5)
         self.assertTrue(diverter.enabled)
         self.assertTrue(diverter.active)
-        self.machine.coils.c_hold.enable.assert_called_once_with()
-        self.machine.coils.c_hold.enable = MagicMock()
-        self.assertTrue(self.machine.coils.c_power.pulse.called)
-        self.machine.coils.c_power.pulse = MagicMock()
-        assert not self.machine.coils.c_hold.disable.called
+        self.machine.coils["c_hold"].enable.assert_called_once_with()
+        self.machine.coils["c_hold"].enable = MagicMock()
+        self.assertTrue(self.machine.coils["c_power"].pulse.called)
+        self.machine.coils["c_power"].pulse = MagicMock()
+        assert not self.machine.coils["c_hold"].disable.called
 
         self.advance_time_and_run(4)
-        assert not self.machine.coils.c_hold.disable.called
+        assert not self.machine.coils["c_hold"].disable.called
 
         self.hit_and_release_switch("s_playfield")
         self.machine_run()
         self.assertFalse(diverter.active)
-        self.machine.coils.c_hold.disable.assert_called_once_with()
+        self.machine.coils["c_hold"].disable.assert_called_once_with()
 
         self.hit_switch_and_run("s_ball_switch1", 1)
         # test inactive side
-        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices.test_target
+        self.machine.playfield.config['default_source_device'] = self.machine.ball_devices["test_target"]
         self.machine.playfield.add_ball()
 
         self.advance_time_and_run(3)
@@ -538,7 +595,7 @@ class TestDiverter(MpfTestCase):
         self.assertFalse(diverter.active)
 
         self.advance_time_and_run(4)
-        assert not self.machine.coils.c_hold.enable.called
-        assert not self.machine.coils.c_power.pulse.called
+        assert not self.machine.coils["c_hold"].enable.called
+        assert not self.machine.coils["c_power"].pulse.called
 
         self.hit_switch_and_run("s_ball_switch1", 1)