    def check_effect(self, canvas, effect, assert_fn,
                     is_blank=True, iterations=40, warm_up=0):
        """
        Basic checks for all effects.  Since they are all randomised to a
        certain extent, just check the overall content for expected values.
        """
        # Asciimatics always calls reset on entering a new Scene.
        effect.reset()

        # Check canvas is in desired starting state.
        if is_blank:
            for x in range(canvas.width):
                for y in range(canvas.height):
                    self.assertEqual(canvas.get_from(x, y), (32, 7, 0, 0))

        # Set up blank my_buffer - OK this should copy the existing screen, but
        # we just lose one iteration on the checks (when not really blank).
        my_buffer = [[(32, 7, 0, 0) for _ in range(40)] for _ in range(10)]

        # Re-draw comparing the my_buffer with what's on the canvas
        for i in range(iterations):
            effect.update(i)
            changed = False
            if i >= warm_up:
                view = ""
                for y in range(canvas.height):
                    for x in range(canvas.width):
                        value = canvas.get_from(x, y)
                        assert_fn(value)
                        if value != my_buffer[y][x]:
                            changed = True
                            my_buffer[y][x] = value
                        view += chr(value[0])
                    view += "\n"
                self.assertTrue(changed, "failed at step %d %s" % (i, view))

        # Check there is no stop frame by default.
        self.assertEqual(effect.stop_frame, 0)
Basic checks for all effects.  Since they are all randomised to a
certain extent, just check the overall content for expected values.
tests/test_particles.py