[pitivi/clipprops: 1/14] tests: Move the utility logic in a single class




commit 0987ea9928224d22508bdd1512985c4150ab70de
Author: Alexandru Băluț <alexandru balut gmail com>
Date:   Wed Sep 9 22:02:30 2020 +0200

    tests: Move the utility logic in a single class

 tests/common.py                    | 111 ++++++++++++++--
 tests/test_clipproperties.py       |  66 ++++------
 tests/test_clipproperties_color.py |  34 ++---
 tests/test_timeline_elements.py    |   7 +-
 tests/test_timeline_markers.py     |  12 +-
 tests/test_timeline_timeline.py    |  36 ++----
 tests/test_undo.py                 |   8 +-
 tests/test_undo_markers.py         |  27 ++--
 tests/test_undo_timeline.py        | 250 ++++++++++++++++---------------------
 tests/test_utils_timeline.py       |   3 +-
 10 files changed, 276 insertions(+), 278 deletions(-)
---
diff --git a/tests/common.py b/tests/common.py
index ae539bd1b..57c301e8b 100644
--- a/tests/common.py
+++ b/tests/common.py
@@ -37,7 +37,7 @@ from gi.repository import Gst
 from gi.repository import Gtk
 
 from pitivi.application import Pitivi
-from pitivi.clipproperties import TransformationProperties
+from pitivi.clipproperties import ClipProperties
 from pitivi.editorstate import EditorState
 from pitivi.project import ProjectManager
 from pitivi.settings import GlobalSettings
@@ -240,20 +240,49 @@ def setup_project_with_clips(func, assets_names=None):
     return wrapper
 
 
-def setup_transformation_box(func):
+def setup_timeline(func):
+    def wrapped(self):
+        self.app = create_pitivi()
+        self.project = self.app.project_manager.new_blank_project()
+        self.timeline = self.project.ges_timeline
+        self.layer = self.timeline.append_layer()
+        self.action_log = self.app.action_log
+
+        project = self.app.project_manager.current_project
+        self.timeline_container = TimelineContainer(self.app, editor_state=self.app.gui.editor.editor_state)
+        self.timeline_container.set_project(project)
+        self.app.gui.editor.timeline_ui = self.timeline_container
+
+        timeline = self.timeline_container.timeline
+        timeline.app.project_manager.current_project = project
+        timeline.get_parent = mock.MagicMock(return_value=self.timeline_container)
+
+        func(self)
+
+        del self.timeline_container
+        del self.action_log
+        del self.layer
+        del self.timeline
+        del self.project
+        del self.app
+
+    return wrapped
+
+
+def setup_clipproperties(func):
     def wrapped(self):
-        has_container = hasattr(self, "timeline_container")
-        if not has_container:
-            self.timeline_container = create_timeline_container()
         app = self.timeline_container.app
-        self.transformation_box = TransformationProperties(app)
-        self.transformation_box._new_project_loaded_cb(app, self.timeline_container._project)
+
+        self.clipproperties = ClipProperties(app)
+        self.clipproperties.new_project_loaded_cb(None, self.project)
+
+        self.transformation_box = self.clipproperties.transformation_expander
+        self.transformation_box._new_project_loaded_cb(None, self.project)
 
         func(self)
 
         del self.transformation_box
-        if not has_container:
-            del self.timeline_container
+        del self.clipproperties
 
     return wrapped
 
@@ -347,6 +376,22 @@ class TestCase(unittest.TestCase, Loggable):
 
         return proj_uri
 
+    def add_clip(self, layer, start, inpoint=0, duration=10, clip_type=GES.TrackType.UNKNOWN):
+        """Creates a clip on the specified layer."""
+        asset = GES.UriClipAsset.request_sync(
+            get_sample_uri("tears_of_steel.webm"))
+        clip = layer.add_asset(asset, start, inpoint, duration, clip_type)
+        self.assertIsNotNone(clip)
+
+        return clip
+
+    def add_clips_simple(self, timeline, num_clips):
+        """Creates a number of clips on a new layer."""
+        layer = timeline.ges_timeline.append_layer()
+        clips = [self.add_clip(layer, i * 10) for i in range(num_clips)]
+        self.assertEqual(len(clips), num_clips)
+        return clips
+
     def toggle_clip_selection(self, ges_clip, expect_selected):
         """Toggles the selection state of @ges_clip."""
         selected = bool(ges_clip.ui.get_state_flags() & Gtk.StateFlags.SELECTED)
@@ -392,6 +437,54 @@ class TestCase(unittest.TestCase, Loggable):
         comments = [ges_marker.get_string("comment") for ges_marker in markers]
         self.assertListEqual(comments, expected_comments)
 
+    def assert_layers(self, layers):
+        self.assertEqual(self.timeline.get_layers(), layers)
+        # Import TestLayers locally, otherwise its tests are discovered and
+        # run twice.
+        from tests.test_timeline_timeline import TestLayers
+        TestLayers.check_priorities_and_positions(self, self.timeline.ui, layers, list(range(len(layers))))
+
+    def assert_effect_count(self, clip, count):
+        effects = [effect for effect in clip.get_children(True)
+                   if isinstance(effect, GES.Effect)]
+        self.assertEqual(len(effects), count)
+
+    def assert_control_source_values(self, control_source, expected_values, expected_timestamps):
+        values = [timed_value.value for timed_value in control_source.get_all()]
+        self.assertListEqual(values, expected_values)
+
+        timestamps = [timed_value.timestamp for timed_value in control_source.get_all()]
+        self.assertListEqual(timestamps, expected_timestamps)
+
+    def get_timeline_clips(self):
+        for layer in self.timeline.layers:
+            for clip in layer.get_clips():
+                yield clip
+
+    def get_transition_element(self, ges_layer):
+        """Gets the first found GES.VideoTransition clip."""
+        for clip in ges_layer.get_clips():
+            if isinstance(clip, GES.TransitionClip):
+                for element in clip.get_children(False):
+                    if isinstance(element, GES.VideoTransition):
+                        return element
+        return None
+
+    @staticmethod
+    def commit_cb(action_log, stack, stacks):
+        stacks.append(stack)
+
+    def _wait_until_project_loaded(self):
+        # Run the mainloop so the project is set up properly so that
+        # the timeline creates transitions automatically.
+        mainloop = create_main_loop()
+
+        def loaded_cb(project, timeline):
+            mainloop.quit()
+        self.app.project_manager.current_project.connect("loaded", loaded_cb)
+        mainloop.run()
+        self.assertTrue(self.timeline.props.auto_transition)
+
 
 @contextlib.contextmanager
 def created_project_file(asset_uri):
diff --git a/tests/test_clipproperties.py b/tests/test_clipproperties.py
index cf9caac60..24744572c 100644
--- a/tests/test_clipproperties.py
+++ b/tests/test_clipproperties.py
@@ -19,17 +19,15 @@
 from unittest import mock
 
 from gi.repository import GES
-from tests import common
-from tests.test_timeline_timeline import BaseTestTimeline
-from tests.test_undo_timeline import BaseTestUndoTimeline
 
-from pitivi.clipproperties import ClipProperties
+from tests import common
 
 
-class TransformationPropertiesTest(BaseTestTimeline):
+class TransformationPropertiesTest(common.TestCase):
     """Tests for the TransformationProperties widget."""
 
-    @common.setup_transformation_box
+    @common.setup_timeline
+    @common.setup_clipproperties
     def test_spin_buttons_read(self):
         """Checks the spin buttons update when the source properties change."""
         # Create transformation box
@@ -59,7 +57,8 @@ class TransformationPropertiesTest(BaseTestTimeline):
             spin_btn_value = spin_buttons[prop].get_value_as_int()
             self.assertEqual(new_val, spin_btn_value)
 
-    @common.setup_transformation_box
+    @common.setup_timeline
+    @common.setup_clipproperties
     def test_spin_buttons_write(self):
         """Checks the spin buttons changing updates the source properties."""
         # Create transformation box
@@ -93,7 +92,8 @@ class TransformationPropertiesTest(BaseTestTimeline):
                 self.assertTrue(ret)
                 self.assertEqual(current_spin_values[source_prop], source_value)
 
-    @common.setup_transformation_box
+    @common.setup_timeline
+    @common.setup_clipproperties
     def test_spin_buttons_source_change(self):
         """Checks the spin buttons update when the selected clip changes."""
         # Create transformation box
@@ -126,7 +126,8 @@ class TransformationPropertiesTest(BaseTestTimeline):
         for prop in ["posx", "posy", "width", "height"]:
             self.assertEqual(spin_buttons[prop].get_value_as_int(), new_values[prop])
 
-    @common.setup_transformation_box
+    @common.setup_timeline
+    @common.setup_clipproperties
     def test_keyframes_activate(self):
         """Checks transformation properties keyframes activation."""
         # Create transformation box
@@ -161,7 +162,8 @@ class TransformationPropertiesTest(BaseTestTimeline):
             self.assertEqual(keyframes, [(inpoint, initial_values[prop]),
                                          (inpoint + duration, initial_values[prop])])
 
-    @common.setup_transformation_box
+    @common.setup_timeline
+    @common.setup_clipproperties
     def test_keyframes_add(self):
         """Checks keyframe creation."""
         # Create transformation box
@@ -194,7 +196,8 @@ class TransformationPropertiesTest(BaseTestTimeline):
                 keyframes = [(item.timestamp, item.value) for item in control_source.get_all()]
                 self.assertEqual((timestamp, value), keyframes[index + 1])
 
-    @common.setup_transformation_box
+    @common.setup_timeline
+    @common.setup_clipproperties
     def test_keyframes_navigation(self):
         """Checks keyframe navigation."""
         # Create transformation box
@@ -243,7 +246,8 @@ class TransformationPropertiesTest(BaseTestTimeline):
             if position in offsets and position != 0:
                 prev_index += 1
 
-    @common.setup_transformation_box
+    @common.setup_timeline
+    @common.setup_clipproperties
     def test_reset_to_default(self):
         """Checks "reset to default" button."""
         # Create transformation box
@@ -276,7 +280,7 @@ class TransformationPropertiesTest(BaseTestTimeline):
             self.assertEqual(value, source.ui.default_position[prop])
 
 
-class ClipPropertiesTest(BaseTestUndoTimeline, BaseTestTimeline):
+class ClipPropertiesTest(common.TestCase):
     """Tests for the TitleProperties class."""
 
     def _get_title_source_child_props(self):
@@ -291,22 +295,13 @@ class ClipPropertiesTest(BaseTestUndoTimeline, BaseTestTimeline):
                                                        "color",
                                                        "foreground-color")]
 
+    @common.setup_timeline
+    @common.setup_clipproperties
     def test_create_title(self):
         """Exercise creating a title clip."""
-        # Wait until the project creates a layer in the timeline.
-        common.create_main_loop().run(until_empty=True)
-
-        # pylint: disable=import-outside-toplevel
-        from pitivi.timeline.timeline import TimelineContainer
-        timeline_container = TimelineContainer(self.app, editor_state=self.app.gui.editor.editor_state)
-        timeline_container.set_project(self.project)
-        self.app.gui.editor.timeline_ui = timeline_container
-
-        clipproperties = ClipProperties(self.app)
-        clipproperties.new_project_loaded_cb(None, self.project)
         self.project.pipeline.get_position = mock.Mock(return_value=0)
 
-        clipproperties.create_title_clip_cb(None)
+        self.clipproperties.create_title_clip_cb(None)
         ps1 = self._get_title_source_child_props()
 
         self.action_log.undo()
@@ -317,27 +312,16 @@ class ClipPropertiesTest(BaseTestUndoTimeline, BaseTestTimeline):
         ps2 = self._get_title_source_child_props()
         self.assertListEqual(ps1, ps2)
 
+    @common.setup_timeline
+    @common.setup_clipproperties
     def test_alignment_editor(self):
         """Exercise aligning a clip using the alignment editor."""
-        # Wait until the project creates a layer in the timeline.
-        common.create_main_loop().run(until_empty=True)
-
-        from pitivi.timeline.timeline import TimelineContainer
-        timeline_container = TimelineContainer(self.app, editor_state=self.app.gui.editor.editor_state)
-        timeline_container.set_project(self.project)
-        self.app.gui.editor.timeline_ui = timeline_container
-
-        clipproperties = ClipProperties(self.app)
-        clipproperties.new_project_loaded_cb(None, self.project)
         self.project.pipeline.get_position = mock.Mock(return_value=0)
 
-        transformation_box = clipproperties.transformation_expander
-        transformation_box._new_project_loaded_cb(self.app, self.project)
-
-        timeline = timeline_container.timeline
+        timeline = self.timeline_container.timeline
         clip = self.add_clips_simple(timeline, 1)[0]
         timeline.selection.select([clip])
-        source = transformation_box.source
+        source = self.transformation_box.source
         self.assertIsNotNone(source)
 
         height = source.get_child_property("height").value
@@ -346,7 +330,7 @@ class ClipPropertiesTest(BaseTestUndoTimeline, BaseTestTimeline):
         self.assertEqual(source.get_child_property("posx").value, 0)
         self.assertEqual(source.get_child_property("posy").value, 0)
 
-        alignment_editor = transformation_box.alignment_editor
+        alignment_editor = self.transformation_box.alignment_editor
         event = mock.MagicMock()
         event.x = 0
         event.y = 0
diff --git a/tests/test_clipproperties_color.py b/tests/test_clipproperties_color.py
index d87dc9769..8227532f6 100644
--- a/tests/test_clipproperties_color.py
+++ b/tests/test_clipproperties_color.py
@@ -20,29 +20,19 @@ from unittest import mock
 
 from gi.repository import GES
 
-from pitivi.clipproperties import ClipProperties
 from tests import common
-from tests.test_undo_timeline import BaseTestUndoTimeline
 
 
-class ColorPropertiesTest(BaseTestUndoTimeline):
+class ColorPropertiesTest(common.TestCase):
     """Tests for the ColorProperties class."""
 
+    @common.setup_timeline
+    @common.setup_clipproperties
     def test_create_hard_coded(self):
         """Exercise creation of a color test clip."""
-        # Wait until the project creates a layer in the timeline.
-        common.create_main_loop().run(until_empty=True)
-
-        from pitivi.timeline.timeline import TimelineContainer
-        timeline_container = TimelineContainer(self.app, editor_state=self.app.gui.editor.editor_state)
-        timeline_container.set_project(self.project)
-        self.app.gui.editor.timeline_ui = timeline_container
-
-        clipproperties = ClipProperties(self.app)
-        clipproperties.new_project_loaded_cb(None, self.project)
         self.project.pipeline.get_position = mock.Mock(return_value=0)
 
-        clipproperties.create_color_clip_cb(None)
+        self.clipproperties.create_color_clip_cb(None)
         clips = self.layer.get_clips()
         pattern = clips[0].get_vpattern()
         self.assertEqual(pattern, GES.VideoTestPattern.SOLID_COLOR)
@@ -53,23 +43,15 @@ class ColorPropertiesTest(BaseTestUndoTimeline):
         self.action_log.redo()
         self.assertListEqual(self.layer.get_clips(), clips)
 
+    @common.setup_timeline
+    @common.setup_clipproperties
     def test_color_change(self):
         """Exercise the changing of colors for color clip."""
-        # Wait until the project creates a layer in the timeline.
-        common.create_main_loop().run(until_empty=True)
-
-        from pitivi.timeline.timeline import TimelineContainer
-        timeline_container = TimelineContainer(self.app, editor_state=self.app.gui.editor.editor_state)
-        timeline_container.set_project(self.project)
-        self.app.gui.editor.timeline_ui = timeline_container
-
-        clipproperties = ClipProperties(self.app)
-        clipproperties.new_project_loaded_cb(None, self.project)
         self.project.pipeline.get_position = mock.Mock(return_value=0)
 
-        clipproperties.create_color_clip_cb(None)
+        self.clipproperties.create_color_clip_cb(None)
 
-        color_expander = clipproperties.color_expander
+        color_expander = self.clipproperties.color_expander
         color_picker_mock = mock.Mock()
         color_picker_mock.calculate_argb.return_value = 1 << 24 | 2 << 16 | 3 << 8 | 4
         color_expander._color_picker_value_changed_cb(color_picker_mock)
diff --git a/tests/test_timeline_elements.py b/tests/test_timeline_elements.py
index 3a34faf75..59c2ecbe8 100644
--- a/tests/test_timeline_elements.py
+++ b/tests/test_timeline_elements.py
@@ -30,10 +30,9 @@ from pitivi.undo.undo import UndoableActionLog
 from pitivi.utils.timeline import Zoomable
 from pitivi.utils.ui import LAYER_HEIGHT
 from tests import common
-from tests.test_timeline_timeline import BaseTestTimeline
 
 
-class TestKeyframeCurve(BaseTestTimeline):
+class TestKeyframeCurve(common.TestCase):
     """Tests for the KeyframeCurve class."""
 
     def test_keyframe_toggle(self):
@@ -250,7 +249,7 @@ class TestKeyframeCurve(BaseTestTimeline):
         self.assertListEqual([item.timestamp for item in control_source.get_all()], [0, 1000000000])
 
 
-class TestVideoSource(BaseTestTimeline):
+class TestVideoSource(common.TestCase):
     """Tests for the VideoSource class."""
 
     def test_video_source_scaling(self):
@@ -330,7 +329,7 @@ class TestVideoSource(BaseTestTimeline):
         self.assertEqual(height, 400)
 
     @common.setup_project_with_clips
-    @common.setup_transformation_box
+    @common.setup_clipproperties
     def test_change_set_project_size(self):
         """Checks the size of the scaled clips after project settings changes."""
         clip, = self.layer.get_clips()
diff --git a/tests/test_timeline_markers.py b/tests/test_timeline_markers.py
index 26b941502..14884fba3 100644
--- a/tests/test_timeline_markers.py
+++ b/tests/test_timeline_markers.py
@@ -22,15 +22,15 @@ from gi.repository import Gdk
 from gi.repository import Gtk
 
 from pitivi.utils.timeline import Zoomable
-from tests.test_undo_timeline import BaseTestUndoTimeline
+from tests import common
 
 
-class TestMarkers(BaseTestUndoTimeline):
+class TestMarkers(common.TestCase):
     """Tests for markers."""
 
+    @common.setup_timeline
     def test_marker_added_ui(self):
         """Checks the add marker UI."""
-        self.setup_timeline_container()
         markers = self.timeline.get_marker_list("markers")
         marker_box = self.timeline_container.markers
         marker_box.markers_container = markers
@@ -51,9 +51,9 @@ class TestMarkers(BaseTestUndoTimeline):
         position = Zoomable.pixel_to_ns(event.x)
         self.assert_markers(markers, [(position, None)])
 
+    @common.setup_timeline
     def test_marker_removed_ui(self):
         """Checks the remove marker UI."""
-        self.setup_timeline_container()
         markers = self.timeline.get_marker_list("markers")
         marker_box = self.timeline_container.markers
         marker_box.markers_container = markers
@@ -77,9 +77,9 @@ class TestMarkers(BaseTestUndoTimeline):
 
         self.assert_markers(markers, [])
 
+    @common.setup_timeline
     def test_marker_moved_ui(self):
         """Checks the move marker UI."""
-        self.setup_timeline_container()
         markers = self.timeline.get_marker_list("markers")
         marker_box = self.timeline_container.markers
         marker_box.markers_container = markers
@@ -111,9 +111,9 @@ class TestMarkers(BaseTestUndoTimeline):
         self.assert_markers(markers, [(position2, None)])
 
     # pylint: disable=unbalanced-tuple-unpacking
+    @common.setup_timeline
     def test_marker_comment_ui(self):
         """Checks the comments marker UI."""
-        self.setup_timeline_container()
         markers = self.timeline.get_marker_list("markers")
         marker_box = self.timeline_container.markers
         marker_box.markers_container = markers
diff --git a/tests/test_timeline_timeline.py b/tests/test_timeline_timeline.py
index d77a4fa6b..65cfd3e5a 100644
--- a/tests/test_timeline_timeline.py
+++ b/tests/test_timeline_timeline.py
@@ -35,27 +35,7 @@ THIN = LAYER_HEIGHT / 2
 THICK = LAYER_HEIGHT
 
 
-class BaseTestTimeline(common.TestCase):
-    """Test case with tools for setting up a timeline."""
-
-    def add_clip(self, layer, start, inpoint=0, duration=10, clip_type=GES.TrackType.UNKNOWN):
-        """Creates a clip on the specified layer."""
-        asset = GES.UriClipAsset.request_sync(
-            common.get_sample_uri("tears_of_steel.webm"))
-        clip = layer.add_asset(asset, start, inpoint, duration, clip_type)
-        self.assertIsNotNone(clip)
-
-        return clip
-
-    def add_clips_simple(self, timeline, num_clips):
-        """Creates a number of clips on a new layer."""
-        layer = timeline.ges_timeline.append_layer()
-        clips = [self.add_clip(layer, i * 10) for i in range(num_clips)]
-        self.assertEqual(len(clips), num_clips)
-        return clips
-
-
-class TestLayers(BaseTestTimeline):
+class TestLayers(common.TestCase):
     """Tests for the layers."""
 
     def test_dragging_layer(self):
@@ -289,7 +269,7 @@ class TestLayers(BaseTestTimeline):
         self.check_priorities_and_positions(timeline, ges_layers, expected_priorities)
 
 
-class TestGrouping(BaseTestTimeline):
+class TestGrouping(common.TestCase):
 
     def __check_can_group_ungroup(self, timeline_container, can_group, can_ungroup):
         self.assertEqual(timeline_container.group_action.props.enabled, can_group)
@@ -505,7 +485,7 @@ class TestGrouping(BaseTestTimeline):
                          "No new layer should have been created")
 
 
-class TestCopyPaste(BaseTestTimeline):
+class TestCopyPaste(common.TestCase):
 
     def copy_clips(self, num_clips):
         timeline_container = common.create_timeline_container()
@@ -579,7 +559,7 @@ class TestCopyPaste(BaseTestTimeline):
         self.assertEqual(len(layer.get_clips()), 1)
 
 
-class TestEditing(BaseTestTimeline):
+class TestEditing(common.TestCase):
 
     def test_trimming_on_layer_separator(self):
         # Create a clip
@@ -616,7 +596,7 @@ class TestEditing(BaseTestTimeline):
                          "No new layer should have been created")
 
 
-class TestShiftSelection(BaseTestTimeline):
+class TestShiftSelection(common.TestCase):
 
     def __reset_clips_selection(self, timeline):
         """Unselects all clips in the timeline."""
@@ -784,7 +764,7 @@ class TestShiftSelection(BaseTestTimeline):
         self.__check_shift_selection_multiple_layers(left_click_also_seeks=True)
 
 
-class TestTimelineContainer(BaseTestTimeline):
+class TestTimelineContainer(common.TestCase):
     """Tests for the TimelineContainer class."""
 
     def test_update_clips_asset(self):
@@ -802,7 +782,7 @@ class TestTimelineContainer(BaseTestTimeline):
         timeline_container.update_clips_asset(mock.Mock(), mock.Mock())
 
 
-class TestClipsEdges(BaseTestTimeline):
+class TestClipsEdges(common.TestCase):
 
     def test_clips_edges(self):
         """Test function for function clips_edges."""
@@ -826,7 +806,7 @@ class TestClipsEdges(BaseTestTimeline):
         self.assertEqual(timeline_container.first_clip_edge(before=20), 15)
 
 
-class TestDragFromOutside(BaseTestTimeline):
+class TestDragFromOutside(common.TestCase):
 
     def setUp(self):
         super().setUp()
diff --git a/tests/test_undo.py b/tests/test_undo.py
index 29a7976d1..7c87a684e 100644
--- a/tests/test_undo.py
+++ b/tests/test_undo.py
@@ -29,7 +29,6 @@ from pitivi.undo.undo import UndoableActionStack
 from pitivi.undo.undo import UndoError
 from pitivi.undo.undo import UndoWrongStateError
 from tests import common
-from tests.test_undo_timeline import BaseTestUndoTimeline
 
 
 class TestUndoableActionStack(common.TestCase):
@@ -416,12 +415,9 @@ class TestUndoableActionLog(common.TestCase):
         self.assertEqual(len(self.log.redo_stacks), 0)
 
 
-class TestRollback(BaseTestUndoTimeline):
-
-    def setUp(self):
-        super().setUp()
-        self.setup_timeline_container()
+class TestRollback(common.TestCase):
 
+    @common.setup_timeline
     def test_rollback_of_nested_operation_does_not_add_actions_to_parent(self):
         clip1 = GES.TitleClip()
         clip1.set_start(0 * Gst.SECOND)
diff --git a/tests/test_undo_markers.py b/tests/test_undo_markers.py
index 0e6f652b4..6d548d090 100644
--- a/tests/test_undo_markers.py
+++ b/tests/test_undo_markers.py
@@ -20,15 +20,14 @@ import tempfile
 from gi.repository import Gst
 
 from tests import common
-from tests.test_undo_timeline import BaseTestUndoTimeline
 
 
-class TestMarkers(BaseTestUndoTimeline):
+class TestMarkers(common.TestCase):
     """Tests for the various classes."""
 
+    @common.setup_timeline
     def test_marker_added(self):
         """Checks marker addition."""
-        self.setup_timeline_container()
         markers = self.timeline.get_marker_list("markers")
 
         with self.action_log.started("Added marker"):
@@ -79,9 +78,9 @@ class TestMarkers(BaseTestUndoTimeline):
             self.action_log.redo()
             self.assert_markers(markers, [(10, "comment 1"), (20, "comment 2")])
 
+    @common.setup_timeline
     def test_marker_removed(self):
         """Checks marker removal."""
-        self.setup_timeline_container()
         markers = self.timeline.get_marker_list("markers")
         marker1 = markers.add(10)
         marker2 = markers.add(20)
@@ -107,9 +106,9 @@ class TestMarkers(BaseTestUndoTimeline):
             self.action_log.redo()
             self.assert_markers(markers, [])
 
+    @common.setup_timeline
     def test_marker_moved(self):
         """Checks marker moving."""
-        self.setup_timeline_container()
         markers = self.timeline.get_marker_list("markers")
         marker1 = markers.add(10)
         markers.add(20)
@@ -130,10 +129,9 @@ class TestMarkers(BaseTestUndoTimeline):
             self.action_log.redo()
             self.assert_markers(markers, [(20, None), (30, None)])
 
+    @common.setup_timeline
     def test_marker_comment(self):
         """Checks marker comment."""
-        self.setup_timeline_container()
-
         markers = self.timeline.get_marker_list("markers")
 
         with self.action_log.started("Added marker"):
@@ -175,6 +173,7 @@ class TestMarkers(BaseTestUndoTimeline):
             self.action_log.redo()
             self.assert_markers(markers, [(10, "comment 1"), (20, "comment 2")])
 
+    @common.setup_timeline
     def test_marker_load_project(self):
         """Checks marker addition."""
         # TODO: When there is nothing connected to closing-project,
@@ -206,7 +205,7 @@ class TestMarkers(BaseTestUndoTimeline):
         project.connect("loaded", loaded_cb)
         mainloop = common.create_main_loop()
         mainloop.run()
-        self.action_log = self.app.action_log
+        action_log = self.app.action_log
 
         markers = project.ges_timeline.get_marker_list("markers")
         self.assert_markers(markers, [(10, None), (20, None)])
@@ -214,23 +213,23 @@ class TestMarkers(BaseTestUndoTimeline):
         ges_markers = markers.get_markers()
         marker1, marker2 = ges_markers
 
-        with self.action_log.started("new comment"):
+        with action_log.started("new comment"):
             marker1.set_string("comment", "comment 1")
         self.assert_markers(markers, [(10, "comment 1"), (20, None)])
 
-        with self.action_log.started("new comment"):
+        with action_log.started("new comment"):
             marker2.set_string("comment", "comment 2")
         self.assert_markers(markers, [(10, "comment 1"), (20, "comment 2")])
 
         for _ in range(4):
-            self.action_log.undo()
+            action_log.undo()
             self.assert_markers(markers, [(10, "comment 1"), (20, None)])
 
-            self.action_log.undo()
+            action_log.undo()
             self.assert_markers(markers, [(10, None), (20, None)])
 
-            self.action_log.redo()
+            action_log.redo()
             self.assert_markers(markers, [(10, "comment 1"), (20, None)])
 
-            self.action_log.redo()
+            action_log.redo()
             self.assert_markers(markers, [(10, "comment 1"), (20, "comment 2")])
diff --git a/tests/test_undo_timeline.py b/tests/test_undo_timeline.py
index 0e4493e24..8e1f012c5 100644
--- a/tests/test_undo_timeline.py
+++ b/tests/test_undo_timeline.py
@@ -26,8 +26,6 @@ from gi.repository import GstController
 from gi.repository import Gtk
 
 from pitivi.timeline.layer import Layer
-from pitivi.timeline.timeline import Timeline
-from pitivi.timeline.timeline import TimelineContainer
 from pitivi.undo.project import AssetAddedAction
 from pitivi.undo.timeline import ClipAdded
 from pitivi.undo.timeline import ClipRemoved
@@ -38,74 +36,9 @@ from pitivi.utils.ui import URI_TARGET_ENTRY
 from tests import common
 
 
-class BaseTestUndoTimeline(common.TestCase):
-
-    def setUp(self):
-        super(BaseTestUndoTimeline, self).setUp()
-        self.app = common.create_pitivi()
-        self.project = self.app.project_manager.new_blank_project()
-        self.timeline = self.project.ges_timeline
-        self.layer = self.timeline.append_layer()
-        self.action_log = self.app.action_log
-        self.timeline_container = None
-
-    def setup_timeline_container(self):
-        project = self.app.project_manager.current_project
-        self.timeline_container = TimelineContainer(self.app, editor_state=self.app.gui.editor.editor_state)
-        self.timeline_container.set_project(project)
-
-        timeline = self.timeline_container.timeline
-        timeline.app.project_manager.current_project = project
-        timeline.get_parent = mock.MagicMock(return_value=self.timeline_container)
-
-    def get_timeline_clips(self):
-        for layer in self.timeline.layers:
-            for clip in layer.get_clips():
-                yield clip
-
-    @staticmethod
-    def commit_cb(action_log, stack, stacks):
-        stacks.append(stack)
-
-    def _wait_until_project_loaded(self):
-        # Run the mainloop so the project is set up properly so that
-        # the timeline creates transitions automatically.
-        mainloop = common.create_main_loop()
-
-        def loaded_cb(project, timeline):
-            mainloop.quit()
-        self.app.project_manager.current_project.connect("loaded", loaded_cb)
-        mainloop.run()
-        self.assertTrue(self.timeline.props.auto_transition)
-
-    def assert_effect_count(self, clip, count):
-        effects = [effect for effect in clip.get_children(True)
-                   if isinstance(effect, GES.Effect)]
-        self.assertEqual(len(effects), count)
-
-    def get_transition_element(self, ges_layer):
-        """Gets the first found GES.VideoTransition clip."""
-        for clip in ges_layer.get_clips():
-            if isinstance(clip, GES.TransitionClip):
-                for element in clip.get_children(False):
-                    if isinstance(element, GES.VideoTransition):
-                        return element
-        return None
-
-    def check_layers(self, layers):
-        self.assertEqual(self.timeline.get_layers(), layers)
-        # Import TestLayers locally, otherwise its tests are discovered and
-        # run twice.
-        from tests.test_timeline_timeline import TestLayers
-        TestLayers.check_priorities_and_positions(self, self.timeline.ui, layers, list(range(len(layers))))
-
-
-class TestSelectionResetWhenRemovingClip(BaseTestUndoTimeline):
-
-    def setUp(self):
-        super().setUp()
-        self.setup_timeline_container()
+class TestSelectionResetWhenRemovingClip(common.TestCase):
 
+    def add_clips_separately(self):
         for i in range(3):
             clip = GES.TitleClip()
             clip.set_start(i * Gst.SECOND)
@@ -122,7 +55,9 @@ class TestSelectionResetWhenRemovingClip(BaseTestUndoTimeline):
             else:
                 self.assertFalse(clip.selected.selected)
 
+    @common.setup_timeline
     def test_redo_delete_when_selected(self):
+        self.add_clips_separately()
         clip1, clip2, clip3 = self.get_timeline_clips()
 
         # Delete clip1.
@@ -138,7 +73,9 @@ class TestSelectionResetWhenRemovingClip(BaseTestUndoTimeline):
         self.action_log.redo()
         self.check_selection()
 
+    @common.setup_timeline
     def test_redo_delete_when_unselected(self):
+        self.add_clips_separately()
         clip1, clip2, clip3 = self.get_timeline_clips()
 
         # Delete clip1.
@@ -154,7 +91,9 @@ class TestSelectionResetWhenRemovingClip(BaseTestUndoTimeline):
         self.action_log.redo()
         self.check_selection(clip2, clip3)
 
+    @common.setup_timeline
     def test_undo_add_when_selected(self):
+        self.add_clips_separately()
         clip1, clip2, clip3 = self.get_timeline_clips()
 
         # Undo clip3 creation when selected.
@@ -162,7 +101,9 @@ class TestSelectionResetWhenRemovingClip(BaseTestUndoTimeline):
         self.action_log.undo()
         self.check_selection()
 
+    @common.setup_timeline
     def test_undo_add_when_unselected(self):
+        self.add_clips_separately()
         clip1, clip2, _ = self.get_timeline_clips()
 
         # Undo clip3 creation when unselected.
@@ -171,15 +112,14 @@ class TestSelectionResetWhenRemovingClip(BaseTestUndoTimeline):
         self.check_selection(clip1, clip2)
 
 
-class TestTimelineObserver(BaseTestUndoTimeline):
+class TestTimelineObserver(common.TestCase):
 
+    @common.setup_timeline
     def test_layer_removed(self):
-        self.setup_timeline_container()
-
         layer1 = self.layer
         layer2 = self.timeline.append_layer()
         layer3 = self.timeline.append_layer()
-        self.check_layers([layer1, layer2, layer3])
+        self.assert_layers([layer1, layer2, layer3])
         self.check_removal(self.timeline.get_layers())
 
     def check_removal(self, ges_layers):
@@ -191,22 +131,21 @@ class TestTimelineObserver(BaseTestUndoTimeline):
             remaining_layers.remove(ges_layer)
 
             ges_layer.control_ui.delete_layer_action.activate(None)
-            self.check_layers(remaining_layers)
+            self.assert_layers(remaining_layers)
 
             self.action_log.undo()
-            self.check_layers(ges_layers)
+            self.assert_layers(ges_layers)
 
             self.action_log.redo()
-            self.check_layers(remaining_layers)
+            self.assert_layers(remaining_layers)
 
             self.check_removal(remaining_layers)
 
             self.action_log.undo()
-            self.check_layers(ges_layers)
+            self.assert_layers(ges_layers)
 
+    @common.setup_timeline
     def test_group_ungroup_clips(self):
-        self.setup_timeline_container()
-
         clip1 = common.create_test_clip(GES.TitleClip)
         clip1.set_start(0 * Gst.SECOND)
         clip1.set_duration(1 * Gst.SECOND)
@@ -252,8 +191,8 @@ class TestTimelineObserver(BaseTestUndoTimeline):
             self.assertIsNone(clip1.get_parent())
             self.assertIsNone(clip2.get_parent())
 
+    @common.setup_timeline
     def test_ungroup_group_clip(self):
-        self.setup_timeline_container()
         timeline = self.timeline_container.timeline
 
         uri = common.get_sample_uri("tears_of_steel.webm")
@@ -304,8 +243,8 @@ class TestTimelineObserver(BaseTestUndoTimeline):
             self.assertEqual(len(clips), 1, clips)
             self.assertEqual(len(clips[0].get_children(False)), 2)
 
+    @common.setup_timeline
     def test_insert_on_first_layer(self):
-        self.setup_timeline_container()
         uri = common.get_sample_uri("tears_of_steel.webm")
         asset = GES.UriClipAsset.request_sync(uri)
         clip1 = asset.extract()
@@ -329,58 +268,59 @@ class TestTimelineObserver(BaseTestUndoTimeline):
         clip2.set_duration(1 * Gst.SECOND)
         self.timeline_container.insert_clips_on_first_layer(clips=[clip2], position=0)
         layers = self.timeline.get_layers()
-        self.check_layers([layers[0], self.layer])
+        self.assert_layers([layers[0], self.layer])
         self.assertEqual(layers[0].get_clips(), [clip2])
         self.assertEqual(layers[1].get_clips(), [clip1])
 
         # Undo insert to create a layer
         self.action_log.undo()
         layers = self.timeline.get_layers()
-        self.check_layers([self.layer])
+        self.assert_layers([self.layer])
         self.assertEqual(layers[0].get_clips(), [clip1])
 
         # Redo insert to create a layer
         self.action_log.redo()
         layers = self.timeline.get_layers()
-        self.check_layers([layers[0], self.layer])
+        self.assert_layers([layers[0], self.layer])
         self.assertEqual(layers[0].get_clips(), [clip2])
         self.assertEqual(layers[1].get_clips(), [clip1])
 
 
-class TestLayerObserver(BaseTestUndoTimeline):
+class TestLayerObserver(common.TestCase):
 
+    @common.setup_timeline
     def test_layer_moved(self):
         layer1 = self.layer
         layer2 = self.timeline.append_layer()
         layer3 = self.timeline.append_layer()
         self.assertEqual(self.timeline.get_layers(), [layer1, layer2, layer3])
 
-        timeline_ui = Timeline(app=self.app, size_group=mock.Mock(), 
editor_state=self.app.gui.editor.editor_state)
-        timeline_ui.set_project(self.app.project_manager.current_project)
+        timeline = self.timeline_container.timeline
 
         # Click and drag a layer control box to move the layer.
-        with mock.patch.object(Gtk, 'get_event_widget') as get_event_widget:
+        with mock.patch.object(Gtk, "get_event_widget") as get_event_widget:
             event = mock.Mock()
             event.get_button.return_value = True, 1
 
             get_event_widget.return_value = layer1.control_ui
-            timeline_ui._button_press_event_cb(None, event=event)
+            timeline._button_press_event_cb(None, event=event)
 
             with mock.patch.object(layer1.control_ui, "translate_coordinates") as translate_coordinates:
                 translate_coordinates.return_value = (0, 0)
-                with mock.patch.object(timeline_ui, "get_layer_at") as get_layer_at:
+                with mock.patch.object(timeline, "get_layer_at") as get_layer_at:
                     get_layer_at.return_value = layer3, None
-                    timeline_ui._motion_notify_event_cb(None, event=event)
+                    timeline._motion_notify_event_cb(None, event=event)
 
-            timeline_ui._button_release_event_cb(None, event=event)
-        self.check_layers([layer2, layer3, layer1])
+            timeline._button_release_event_cb(None, event=event)
+        self.assert_layers([layer2, layer3, layer1])
 
         self.action_log.undo()
-        self.check_layers([layer1, layer2, layer3])
+        self.assert_layers([layer1, layer2, layer3])
 
         self.action_log.redo()
-        self.check_layers([layer2, layer3, layer1])
+        self.assert_layers([layer2, layer3, layer1])
 
+    @common.setup_timeline
     def test_layer_renamed(self):
         layer = Layer(self.layer, timeline=mock.Mock())
         self.assertIsNone(layer._name_if_set())
@@ -395,8 +335,8 @@ class TestLayerObserver(BaseTestUndoTimeline):
         self.action_log.redo()
         self.assertEqual(layer._name_if_set(), "Beautiful name")
 
+    @common.setup_timeline
     def test_add_clip(self):
-        self.setup_timeline_container()
         clip1 = GES.TitleClip()
         with self.action_log.started("add clip"):
             self.layer.add_clip(clip1)
@@ -412,10 +352,10 @@ class TestLayerObserver(BaseTestUndoTimeline):
         self.action_log.redo()
         self.assertTrue(clip1 in self.get_timeline_clips())
 
+    @common.setup_timeline
     def test_remove_clip(self):
-        self.setup_timeline_container()
         stacks = []
-        self.action_log.connect("commit", BaseTestUndoTimeline.commit_cb, stacks)
+        self.action_log.connect("commit", common.TestCase.commit_cb, stacks)
 
         clip1 = GES.TitleClip()
         self.layer.add_clip(clip1)
@@ -435,8 +375,8 @@ class TestLayerObserver(BaseTestUndoTimeline):
         self.action_log.redo()
         self.assertFalse(clip1 in self.get_timeline_clips())
 
+    @common.setup_timeline
     def test_layer_added(self):
-        self.setup_timeline_container()
         layers = self.timeline.get_layers()
         self.assertEqual(len(layers), 1)
 
@@ -448,7 +388,7 @@ class TestLayerObserver(BaseTestUndoTimeline):
         layers = self.timeline.get_layers()
         self.assertEqual(len(layers), 2)
         self.assertEqual(layers[0], self.layer)
-        self.check_layers(layers)
+        self.assert_layers(layers)
         self.assertEqual(layers[0].get_clips(), [clip])
         self.assertEqual(layers[1].get_clips(), [])
 
@@ -456,21 +396,21 @@ class TestLayerObserver(BaseTestUndoTimeline):
         layers = self.timeline.get_layers()
         self.assertEqual(len(layers), 1)
         self.assertEqual(layers[0], self.layer)
-        self.check_layers(layers)
+        self.assert_layers(layers)
         self.assertEqual(layers[0].get_clips(), [clip])
 
         self.action_log.redo()
         layers = self.timeline.get_layers()
         self.assertEqual(len(layers), 2)
         self.assertEqual(layers[0], self.layer)
-        self.check_layers(layers)
+        self.assert_layers(layers)
         self.assertEqual(layers[0].get_clips(), [clip])
         self.assertEqual(layers[1].get_clips(), [])
 
+    @common.setup_timeline
     def test_ungroup_group_clip(self):
         # This test is in TestLayerObserver because the relevant operations
         # recorded are clip-added and clip-removed.
-        self.setup_timeline_container()
         uri = common.get_sample_uri("tears_of_steel.webm")
         asset = GES.UriClipAsset.request_sync(uri)
         clip1 = asset.extract()
@@ -507,8 +447,8 @@ class TestLayerObserver(BaseTestUndoTimeline):
         self.assertEqual(5 * Gst.SECOND, timeline_clips[1].get_start())
         self.assertEqual(0.5 * Gst.SECOND, timeline_clips[1].get_duration())
 
+    @common.setup_timeline
     def test_split_clip(self):
-        self.setup_timeline_container()
         clip = GES.TitleClip()
         clip.set_start(0 * Gst.SECOND)
         clip.set_duration(20 * Gst.SECOND)
@@ -533,9 +473,10 @@ class TestLayerObserver(BaseTestUndoTimeline):
         self.action_log.redo()
         self.assertEqual(3, len(self.layer.get_clips()))
 
+    @common.setup_timeline
     def test_add_effect_to_clip(self):
         stacks = []
-        self.action_log.connect("commit", BaseTestUndoTimeline.commit_cb, stacks)
+        self.action_log.connect("commit", common.TestCase.commit_cb, stacks)
 
         clip1 = GES.TitleClip()
         self.layer.add_clip(clip1)
@@ -563,9 +504,10 @@ class TestLayerObserver(BaseTestUndoTimeline):
                                  clip1.get_children(True)
                                  if isinstance(effect, GES.Effect)]))
 
+    @common.setup_timeline
     def test_remove_effect_from_clip(self):
         stacks = []
-        self.action_log.connect("commit", BaseTestUndoTimeline.commit_cb, stacks)
+        self.action_log.connect("commit", common.TestCase.commit_cb, stacks)
 
         clip1 = GES.TitleClip()
         self.layer.add_clip(clip1)
@@ -595,6 +537,7 @@ class TestLayerObserver(BaseTestUndoTimeline):
         self.action_log.redo()
         self.assert_effect_count(clip1, 0)
 
+    @common.setup_timeline
     def test_move_clip(self):
         self._wait_until_project_loaded()
 
@@ -623,9 +566,9 @@ class TestLayerObserver(BaseTestUndoTimeline):
         self.assertEqual(clip2.get_start(), 20 * Gst.SECOND)
         self.assertEqual(len(self.layer.get_clips()), 2)
 
+    @common.setup_timeline
     def test_transition_type(self):
         """Checks the transitions keep their type."""
-        self.setup_timeline_container()
         self._wait_until_project_loaded()
         uri = common.get_sample_uri("tears_of_steel.webm")
         asset = GES.UriClipAsset.request_sync(uri)
@@ -709,6 +652,7 @@ class TestLayerObserver(BaseTestUndoTimeline):
                              "UndoableAutomaticObjectAction is not updated when "
                              "redoing clip add.")
 
+    @common.setup_timeline
     def test_transition_found(self):
         self._wait_until_project_loaded()
         uri = common.get_sample_uri("1sec_simpsons_trailer.mp4")
@@ -733,9 +677,9 @@ class TestLayerObserver(BaseTestUndoTimeline):
         self.action_log.redo()
         self.assertIsNotNone(self.get_transition_element(self.layer))
 
+    @common.setup_timeline
     def test_paste_undo(self):
         """Checks a paste operation can be undone."""
-        self.setup_timeline_container()
         timeline = self.timeline_container.timeline
         project = timeline.ges_timeline.get_asset()
 
@@ -768,8 +712,9 @@ class TestLayerObserver(BaseTestUndoTimeline):
         self.assertEqual(len(self.layer.get_clips()), 2)
 
 
-class TestControlSourceObserver(BaseTestUndoTimeline):
+class TestControlSourceObserver(common.TestCase):
 
+    @common.setup_timeline
     def test_control_source_value_added(self):
         uri = common.get_sample_uri("tears_of_steel.webm")
         asset = GES.UriClipAsset.request_sync(uri)
@@ -780,20 +725,22 @@ class TestControlSourceObserver(BaseTestUndoTimeline):
 
         control_source = GstController.InterpolationControlSource()
         control_source.props.mode = GstController.InterpolationMode.LINEAR
+        self.assert_control_source_values(control_source, [], [])
+
         source.set_control_source(control_source, "alpha", "direct")
+        self.assert_control_source_values(control_source, [1, 1], [0, 2003000000])
 
         with self.action_log.started("keyframe added"):
             self.assertTrue(control_source.set(Gst.SECOND * 0.5, 0.2))
+        self.assert_control_source_values(control_source, [1, 0.2, 1], [0, Gst.SECOND * 0.5, 2003000000])
 
-        self.assertEqual(1, len(control_source.get_all()))
         self.action_log.undo()
-        self.assertEqual(0, len(control_source.get_all()))
+        self.assert_control_source_values(control_source, [1, 1], [0, 2003000000])
+
         self.action_log.redo()
-        keyframes = control_source.get_all()
-        self.assertEqual(1, len(keyframes))
-        self.assertEqual(Gst.SECOND * 0.5, keyframes[0].timestamp)
-        self.assertEqual(0.2, keyframes[0].value)
+        self.assert_control_source_values(control_source, [1, 0.2, 1], [0, Gst.SECOND * 0.5, 2003000000])
 
+    @common.setup_timeline
     def test_control_source_value_removed(self):
         uri = common.get_sample_uri("tears_of_steel.webm")
         asset = GES.UriClipAsset.request_sync(uri)
@@ -804,21 +751,25 @@ class TestControlSourceObserver(BaseTestUndoTimeline):
 
         control_source = GstController.InterpolationControlSource()
         control_source.props.mode = GstController.InterpolationMode.LINEAR
+        self.assert_control_source_values(control_source, [], [])
+
         source.set_control_source(control_source, "alpha", "direct")
+        self.assert_control_source_values(control_source, [1, 1], [0, 2003000000])
+
         self.assertTrue(control_source.set(Gst.SECOND * 0.5, 0.2))
+        self.assert_control_source_values(control_source, [1, 0.2, 1], [0, Gst.SECOND * 0.5, 2003000000])
 
         with self.action_log.started("keyframe removed"):
             self.assertTrue(control_source.unset(Gst.SECOND * 0.5))
+        self.assert_control_source_values(control_source, [1, 1], [0, 2003000000])
 
-        self.assertEqual(0, len(control_source.get_all()))
         self.action_log.undo()
-        keyframes = control_source.get_all()
-        self.assertEqual(1, len(keyframes))
-        self.assertEqual(Gst.SECOND * 0.5, keyframes[0].timestamp)
-        self.assertEqual(0.2, keyframes[0].value)
+        self.assert_control_source_values(control_source, [1, 0.2, 1], [0, Gst.SECOND * 0.5, 2003000000])
+
         self.action_log.redo()
-        self.assertEqual(0, len(control_source.get_all()))
+        self.assert_control_source_values(control_source, [1, 1], [0, 2003000000])
 
+    @common.setup_timeline
     def test_control_source_value_changed(self):
         uri = common.get_sample_uri("tears_of_steel.webm")
         asset = GES.UriClipAsset.request_sync(uri)
@@ -829,20 +780,26 @@ class TestControlSourceObserver(BaseTestUndoTimeline):
 
         control_source = GstController.InterpolationControlSource()
         control_source.props.mode = GstController.InterpolationMode.LINEAR
+        self.assert_control_source_values(control_source, [], [])
+
         source.set_control_source(control_source, "alpha", "direct")
+        self.assert_control_source_values(control_source, [1, 1], [0, 2003000000])
+
         self.assertTrue(control_source.set(Gst.SECOND * 0.5, 0.2))
+        self.assert_control_source_values(control_source, [1, 0.2, 1], [0, Gst.SECOND * 0.5, 2003000000])
 
         with self.action_log.started("keyframe changed"):
             self.assertTrue(control_source.set(Gst.SECOND * 0.5, 0.9))
+        self.assert_control_source_values(control_source, [1, 0.9, 1], [0, Gst.SECOND * 0.5, 2003000000])
 
-        self.assertEqual(0.9, control_source.get_all()[0].value)
         self.action_log.undo()
-        self.assertEqual(0.2, control_source.get_all()[0].value)
+        self.assert_control_source_values(control_source, [1, 0.2, 1], [0, Gst.SECOND * 0.5, 2003000000])
+
         self.action_log.redo()
-        self.assertEqual(0.9, control_source.get_all()[0].value)
+        self.assert_control_source_values(control_source, [1, 0.9, 1], [0, Gst.SECOND * 0.5, 2003000000])
 
 
-class TestTrackElementObserver(BaseTestUndoTimeline):
+class TestTrackElementObserver(common.TestCase):
 
     def assert_effects(self, clip, *effects):
         # Make sure there are no other effects.
@@ -857,9 +814,10 @@ class TestTrackElementObserver(BaseTestUndoTimeline):
                    for effect in effects]
         self.assertEqual(indexes, list(range(len(effects))))
 
+    @common.setup_timeline
     def test_effects_index(self):
         stacks = []
-        self.action_log.connect("commit", BaseTestUndoTimeline.commit_cb, stacks)
+        self.action_log.connect("commit", common.TestCase.commit_cb, stacks)
 
         clip1 = GES.TitleClip()
         self.layer.add_clip(clip1)
@@ -882,9 +840,10 @@ class TestTrackElementObserver(BaseTestUndoTimeline):
         self.action_log.redo()
         self.assert_effects(clip1, effect2, effect1)
 
+    @common.setup_timeline
     def test_effects_index_with_removal(self):
         stacks = []
-        self.action_log.connect("commit", BaseTestUndoTimeline.commit_cb, stacks)
+        self.action_log.connect("commit", common.TestCase.commit_cb, stacks)
 
         clip1 = GES.TitleClip()
         self.layer.add_clip(clip1)
@@ -939,8 +898,9 @@ class TestTrackElementObserver(BaseTestUndoTimeline):
         self.assert_effects(clip1, effect1, effect3)
 
 
-class TestTimelineElementObserver(BaseTestUndoTimeline):
+class TestTimelineElementObserver(common.TestCase):
 
+    @common.setup_timeline
     def test_track_element_property_changed(self):
         clip1 = GES.TitleClip()
         self.layer.add_clip(clip1)
@@ -955,9 +915,10 @@ class TestTimelineElementObserver(BaseTestUndoTimeline):
         self.action_log.redo()
         self.assertEqual(source.get_child_property("text")[1], "pigs fly!")
 
+    @common.setup_timeline
     def test_add_effect_change_property(self):
         stacks = []
-        self.action_log.connect("commit", BaseTestUndoTimeline.commit_cb, stacks)
+        self.action_log.connect("commit", common.TestCase.commit_cb, stacks)
 
         clip1 = GES.TitleClip()
         self.layer.add_clip(clip1)
@@ -1007,11 +968,12 @@ class TestTimelineElementObserver(BaseTestUndoTimeline):
         self.assertEqual(effect1.get_child_property("scratch-lines")[1], 0)
 
 
-class TestGObjectObserver(BaseTestUndoTimeline):
+class TestGObjectObserver(common.TestCase):
 
+    @common.setup_timeline
     def test_clip_property_change(self):
         stacks = []
-        self.action_log.connect("commit", BaseTestUndoTimeline.commit_cb, stacks)
+        self.action_log.connect("commit", common.TestCase.commit_cb, stacks)
 
         # We are not dropping clips here...
         self.app.gui.editor.timeline_ui.timeline.dropping_clips = False
@@ -1045,6 +1007,7 @@ class TestGObjectObserver(BaseTestUndoTimeline):
         self.action_log.redo()
         self.assertEqual(20, clip1.get_priority())
 
+    @common.setup_timeline
     def test_effect_toggling(self):
         clip1 = GES.TitleClip()
         self.layer.add_clip(clip1)
@@ -1093,11 +1056,10 @@ class TestGObjectObserver(BaseTestUndoTimeline):
         self.assertFalse(effect1.props.active)
 
 
-class TestDragDropUndo(BaseTestUndoTimeline):
+class TestDragDropUndo(common.TestCase):
 
     def clip_dragged_to_create_layer(self, below):
         """Simulates dragging a clip on a separator, without dropping it."""
-        self.setup_timeline_container()
         timeline_ui = self.timeline_container.timeline
         layers = self.timeline.get_layers()
         self.assertEqual(len(layers), 1)
@@ -1129,6 +1091,7 @@ class TestDragDropUndo(BaseTestUndoTimeline):
 
         return clip, event, timeline_ui
 
+    @common.setup_timeline
     def test_clip_dragged_to_create_layer_below_denied(self):
         """Checks clip dropped onto the separator below without hovering."""
         clip, event, timeline_ui = self.clip_dragged_to_create_layer(True)
@@ -1138,13 +1101,14 @@ class TestDragDropUndo(BaseTestUndoTimeline):
         layers = self.timeline.get_layers()
         self.assertEqual(len(layers), 1)
         self.assertEqual(layers[0], self.layer)
-        self.check_layers(layers)
+        self.assert_layers(layers)
         self.assertEqual(layers[0].get_clips(), [clip])
 
         stack = self.action_log.undo_stacks[0]
         # Only the clip creation action should be on the stack.
         self.assertEqual(len(stack.done_actions), 1, stack.done_actions)
 
+    @common.setup_timeline
     def test_clip_dragged_to_create_layer_below(self):
         """Checks clip dropped onto the separator below after hovering."""
         clip, event, timeline_ui = self.clip_dragged_to_create_layer(True)
@@ -1155,7 +1119,7 @@ class TestDragDropUndo(BaseTestUndoTimeline):
         layers = self.timeline.get_layers()
         self.assertEqual(len(layers), 2)
         self.assertEqual(layers[0], self.layer)
-        self.check_layers(layers)
+        self.assert_layers(layers)
         self.assertEqual(layers[0].get_clips(), [])
         self.assertEqual(layers[1].get_clips(), [clip])
 
@@ -1163,17 +1127,18 @@ class TestDragDropUndo(BaseTestUndoTimeline):
         layers = self.timeline.get_layers()
         self.assertEqual(len(layers), 1)
         self.assertEqual(layers[0], self.layer)
-        self.check_layers(layers)
+        self.assert_layers(layers)
         self.assertEqual(layers[0].get_clips(), [clip])
 
         self.action_log.redo()
         layers = self.timeline.get_layers()
         self.assertEqual(len(layers), 2)
         self.assertEqual(layers[0], self.layer)
-        self.check_layers(layers)
+        self.assert_layers(layers)
         self.assertEqual(layers[0].get_clips(), [])
         self.assertEqual(layers[1].get_clips(), [clip])
 
+    @common.setup_timeline
     def test_clip_dragged_to_create_layer_above_denied(self):
         """Checks clip dropped onto the separator above without hovering."""
         clip, event, timeline_ui = self.clip_dragged_to_create_layer(False)
@@ -1182,13 +1147,14 @@ class TestDragDropUndo(BaseTestUndoTimeline):
 
         layers = self.timeline.get_layers()
         self.assertEqual(len(layers), 1)
-        self.check_layers(layers)
+        self.assert_layers(layers)
         self.assertEqual(layers[0].get_clips(), [clip])
 
         stack = self.action_log.undo_stacks[0]
         # Only the clip creation action should be on the stack.
         self.assertEqual(len(stack.done_actions), 1, stack.done_actions)
 
+    @common.setup_timeline
     def test_clip_dragged_to_create_layer_above(self):
         """Checks clip dropped onto the separator above after hovering."""
         clip, event, timeline_ui = self.clip_dragged_to_create_layer(False)
@@ -1199,27 +1165,27 @@ class TestDragDropUndo(BaseTestUndoTimeline):
         layers = self.timeline.get_layers()
         self.assertEqual(len(layers), 2)
         self.assertEqual(layers[1], self.layer)
-        self.check_layers(layers)
+        self.assert_layers(layers)
         self.assertEqual(layers[0].get_clips(), [clip])
         self.assertEqual(layers[1].get_clips(), [])
 
         self.action_log.undo()
         layers = self.timeline.get_layers()
         self.assertEqual(len(layers), 1)
-        self.check_layers(layers)
+        self.assert_layers(layers)
         self.assertEqual(layers[0].get_clips(), [clip])
 
         self.action_log.redo()
         layers = self.timeline.get_layers()
         self.assertEqual(len(layers), 2)
         self.assertEqual(layers[1], self.layer)
-        self.check_layers(layers)
+        self.assert_layers(layers)
         self.assertEqual(layers[0].get_clips(), [clip])
         self.assertEqual(layers[1].get_clips(), [])
 
+    @common.setup_timeline
     def test_media_library_asset_dragged_on_separator(self):
         """Simulate dragging an asset from the media library to the timeline."""
-        self.setup_timeline_container()
         timeline_ui = self.timeline_container.timeline
         project = self.app.project_manager.current_project
         layers = self.timeline.get_layers()
diff --git a/tests/test_utils_timeline.py b/tests/test_utils_timeline.py
index c315b2857..042ce6fae 100644
--- a/tests/test_utils_timeline.py
+++ b/tests/test_utils_timeline.py
@@ -25,7 +25,6 @@ from pitivi.utils.timeline import Selected
 from pitivi.utils.timeline import Selection
 from pitivi.utils.timeline import UNSELECT
 from tests import common
-from tests.test_timeline_timeline import BaseTestTimeline
 
 
 class TestSelected(common.TestCase):
@@ -41,7 +40,7 @@ class TestSelected(common.TestCase):
         self.assertFalse(selected)
 
 
-class TestSelection(BaseTestTimeline):
+class TestSelection(common.TestCase):
 
     def test_bool_evaluation(self):
         clip1 = mock.MagicMock()


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]