diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs
deleted file mode 100644
index 30ad5871f2..0000000000
--- a/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
-// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-
-using osu.Framework.Configuration;
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Containers;
-using osu.Framework.Graphics.Shapes;
-using osu.Framework.Graphics.Sprites;
-using osu.Framework.Graphics.UserInterface;
-using osu.Game.Graphics.Sprites;
-using osu.Game.Rulesets.Objects;
-using osu.Game.Rulesets.Objects.Drawables;
-using osu.Game.Rulesets.Timing;
-using OpenTK;
-using OpenTK.Graphics;
-using osu.Game.Rulesets.UI;
-using osu.Game.Rulesets.Judgements;
-using System;
-
-namespace osu.Desktop.Tests.Visual
-{
-    public class TestCaseScrollingHitObjects : OsuTestCase
-    {
-        public override string Description => "SpeedAdjustmentContainer/ScrollingContainer";
-
-        private readonly BindableDouble timeRangeBindable;
-        private readonly OsuSpriteText bottomLabel;
-        private readonly SpriteText topTime;
-        private readonly SpriteText bottomTime;
-
-        public TestCaseScrollingHitObjects()
-        {
-            OsuSpriteText timeRangeText;
-
-            timeRangeBindable = new BindableDouble(2000)
-            {
-                MinValue = 200,
-                MaxValue = 4000,
-            };
-
-            SliderBar<double> timeRange;
-            Add(timeRange = new BasicSliderBar<double>
-            {
-                Size = new Vector2(200, 20),
-                SelectionColor = Color4.Pink,
-                KeyboardStep = 100
-            });
-
-            Add(timeRangeText = new OsuSpriteText
-            {
-                X = 210,
-                TextSize = 16,
-            });
-
-            timeRange.Current.BindTo(timeRangeBindable);
-            timeRangeBindable.ValueChanged += v => timeRangeText.Text = $"Visible Range: {v:#,#.#}";
-            timeRangeBindable.ValueChanged += v => bottomLabel.Text = $"t minus {v:#,#}";
-
-            AddRange(new Drawable[]
-            {
-                new Container
-                {
-                    Anchor = Anchor.Centre,
-                    Origin = Anchor.Centre,
-                    Size = new Vector2(100, 500),
-                    Children = new Drawable[]
-                    {
-                        new Box
-                        {
-                            RelativeSizeAxes = Axes.Both,
-                            Alpha = 0.25f
-                        },
-                        new OsuSpriteText
-                        {
-                            Text = "t minus 0",
-                            Margin = new MarginPadding(2),
-                            TextSize = 14,
-                            Anchor = Anchor.TopRight,
-                        },
-                        bottomLabel = new OsuSpriteText
-                        {
-                            Text = "t minus x",
-                            Margin = new MarginPadding(2),
-                            TextSize = 14,
-                            Anchor = Anchor.BottomRight,
-                            Origin = Anchor.BottomLeft,
-                        },
-                        topTime = new OsuSpriteText
-                        {
-                            Margin = new MarginPadding(2),
-                            TextSize = 14,
-                            Anchor = Anchor.TopLeft,
-                            Origin = Anchor.TopRight,
-                        },
-                        bottomTime = new OsuSpriteText
-                        {
-                            Margin = new MarginPadding(2),
-                            TextSize = 14,
-                            Anchor = Anchor.BottomLeft,
-                            Origin = Anchor.BottomRight,
-                        },
-                    }
-                }
-            });
-
-            timeRangeBindable.TriggerChange();
-        }
-
-        protected override void Update()
-        {
-            base.Update();
-
-            bottomTime.Text = (Time.Current + timeRangeBindable.Value).ToString("#,#");
-        }
-
-        private class TestSpeedAdjustmentContainer : SpeedAdjustmentContainer
-        {
-            public override bool RemoveWhenNotAlive => false;
-
-            public TestSpeedAdjustmentContainer(MultiplierControlPoint controlPoint)
-                : base(controlPoint)
-            {
-            }
-
-            protected override ScrollingContainer CreateScrollingContainer() => new TestScrollingContainer(ControlPoint);
-
-            private class TestScrollingContainer : ScrollingContainer
-            {
-                private readonly MultiplierControlPoint controlPoint;
-
-                public TestScrollingContainer(MultiplierControlPoint controlPoint)
-                {
-                    this.controlPoint = controlPoint;
-                }
-
-                protected override void Update()
-                {
-                    base.Update();
-
-                    Y = (float)(controlPoint.StartTime - Time.Current);
-                }
-            }
-        }
-
-        private class TestDrawableHitObject : DrawableScrollingHitObject<HitObject, Judgement>
-        {
-            private readonly Box background;
-            private const float height = 14;
-
-            public TestDrawableHitObject(HitObject hitObject)
-                : base(hitObject)
-            {
-                AutoSizeAxes = Axes.Y;
-                RelativeSizeAxes = Axes.X;
-                RelativePositionAxes = Axes.Y;
-
-                Y = (float)hitObject.StartTime;
-
-                Children = new Drawable[]
-                {
-                    background = new Box
-                    {
-                        RelativeSizeAxes = Axes.X,
-                        Height = height,
-                    },
-                    new Box
-                    {
-                        RelativeSizeAxes = Axes.X,
-                        Colour = Color4.Cyan,
-                        Height = 1,
-                    },
-                    new OsuSpriteText
-                    {
-                        Anchor = Anchor.Centre,
-                        Origin = Anchor.Centre,
-                        Colour = Color4.Black,
-                        TextSize = height,
-                        Font = @"Exo2.0-BoldItalic",
-                        Text = $"{hitObject.StartTime:#,#}"
-                    }
-                };
-            }
-
-            protected override void LoadComplete()
-            {
-                base.LoadComplete();
-                this.FadeInFromZero(250, Easing.OutQuint);
-            }
-
-            protected override void Update()
-            {
-                base.Update();
-                if (Time.Current >= HitObject.StartTime)
-                    background.Colour = Color4.Red;
-            }
-
-            protected override Judgement CreateJudgement() => new TestJudgement();
-
-            protected override void UpdateState(ArmedState state)
-            {
-            }
-
-            private class TestJudgement : Judgement
-            {
-                public override string ResultString { get { throw new NotImplementedException(); } }
-                public override string MaxResultString { get { throw new NotImplementedException(); } }
-            }
-        }
-    }
-}
diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs
new file mode 100644
index 0000000000..07f59fe876
--- /dev/null
+++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Collections.Generic;
+using OpenTK;
+using osu.Desktop.Tests.Beatmaps;
+using osu.Framework.Extensions;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Framework.Testing;
+using osu.Framework.Timing;
+using osu.Game.Beatmaps;
+using osu.Game.Rulesets;
+using osu.Game.Rulesets.Beatmaps;
+using osu.Game.Rulesets.Judgements;
+using osu.Game.Rulesets.Objects;
+using osu.Game.Rulesets.Objects.Drawables;
+using osu.Game.Rulesets.Osu.Objects;
+using osu.Game.Rulesets.Scoring;
+using osu.Game.Rulesets.Timing;
+using osu.Game.Rulesets.UI;
+
+namespace osu.Desktop.Tests.Visual
+{
+    /// <summary>
+    /// The most minimal implementation of a playfield with scrolling hit objects.
+    /// </summary>
+    public class TestCaseScrollingPlayfield : TestCase
+    {
+        public TestCaseScrollingPlayfield()
+        {
+            Clock = new FramedClock();
+
+            var objects = new List<HitObject>();
+
+            int time = 1500;
+            for (int i = 0; i < 50; i++)
+            {
+                objects.Add(new TestHitObject { StartTime = time });
+
+                time += 500;
+            }
+
+            Beatmap b = new Beatmap
+            {
+                HitObjects = objects,
+                BeatmapInfo = new BeatmapInfo
+                {
+                    Difficulty = new BeatmapDifficulty(),
+                    Metadata = new BeatmapMetadata
+                    {
+                        Artist = @"Unknown",
+                        Title = @"Sample Beatmap",
+                        Author = @"peppy",
+                    }
+                }
+            };
+
+            WorkingBeatmap beatmap = new TestWorkingBeatmap(b);
+
+            Add(new TestHitRenderer(beatmap, true));
+        }
+
+        private class TestHitRenderer : SpeedAdjustedHitRenderer<TestPlayfield, TestHitObject, TestJudgement>
+        {
+            public TestHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset)
+                : base(beatmap, isForCurrentRuleset)
+            {
+            }
+
+            public override ScoreProcessor CreateScoreProcessor() => new TestScoreProcessor();
+
+            protected override BeatmapConverter<TestHitObject> CreateBeatmapConverter() => new TestBeatmapConverter();
+
+            protected override Playfield<TestHitObject, TestJudgement> CreatePlayfield() => new TestPlayfield();
+
+            protected override DrawableHitObject<TestHitObject, TestJudgement> GetVisualRepresentation(TestHitObject h) => new DrawableTestHitObject(h);
+        }
+
+        private class TestScoreProcessor : ScoreProcessor<TestHitObject, TestJudgement>
+        {
+            protected override void OnNewJudgement(TestJudgement judgement)
+            {
+            }
+        }
+
+        private class TestBeatmapConverter : BeatmapConverter<TestHitObject>
+        {
+            protected override IEnumerable<Type> ValidConversionTypes => new[] { typeof(HitObject) };
+
+            protected override IEnumerable<TestHitObject> ConvertHitObject(HitObject original, Beatmap beatmap)
+            {
+                yield return original as TestHitObject;
+            }
+        }
+
+        private class DrawableTestHitObject : DrawableScrollingHitObject<TestHitObject, TestJudgement>
+        {
+            public DrawableTestHitObject(TestHitObject hitObject)
+                : base(hitObject)
+            {
+                Anchor = Anchor.CentreLeft;
+                Origin = Anchor.Centre;
+
+                AutoSizeAxes = Axes.Both;
+
+                Add(new Circle
+                {
+                    Size = new Vector2(50)
+                });
+            }
+
+            protected override TestJudgement CreateJudgement() => new TestJudgement();
+
+            protected override void UpdateState(ArmedState state)
+            {
+            }
+        }
+
+        private class TestPlayfield : ScrollingPlayfield<TestHitObject, TestJudgement>
+        {
+            protected override Container<Drawable> Content => content;
+            private readonly Container<Drawable> content;
+
+            public TestPlayfield()
+                : base(Axes.X)
+            {
+                InternalChildren = new Drawable[]
+                {
+                    new Box
+                    {
+                        RelativeSizeAxes = Axes.Both,
+                        Alpha = 0.2f
+                    },
+                    content = new Container { RelativeSizeAxes = Axes.Both }
+                };
+            }
+        }
+
+
+        private class TestHitObject : HitObject
+        {
+        }
+
+        private class TestJudgement : Judgement
+        {
+            public override string ResultString { get { throw new NotImplementedException(); } }
+            public override string MaxResultString { get { throw new NotImplementedException(); } }
+        }
+    }
+}
\ No newline at end of file
diff --git a/osu.Desktop.Tests/osu.Desktop.Tests.csproj b/osu.Desktop.Tests/osu.Desktop.Tests.csproj
index 5058d2eed5..87ec805288 100644
--- a/osu.Desktop.Tests/osu.Desktop.Tests.csproj
+++ b/osu.Desktop.Tests/osu.Desktop.Tests.csproj
@@ -98,7 +98,7 @@
     <Compile Include="Visual\TestCaseResults.cs" />
     <Compile Include="Visual\TestCaseRoomInspector.cs" />
     <Compile Include="Visual\TestCaseScoreCounter.cs" />
-    <Compile Include="Visual\TestCaseScrollingHitObjects.cs" />
+    <Compile Include="Visual\TestCaseScrollingPlayfield.cs" />
     <Compile Include="Visual\TestCaseSettings.cs" />
     <Compile Include="Visual\TestCaseSkipButton.cs" />
     <Compile Include="Visual\TestCaseSocial.cs" />