diff --git a/osu-framework b/osu-framework
index cd2b351de3..af9ffbd8b9 160000
--- a/osu-framework
+++ b/osu-framework
@@ -1 +1 @@
-Subproject commit cd2b351de37f17b6d91d1fc062627208a09c3834
+Subproject commit af9ffbd8b945e526801c469dd55464363e502962
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetailArea.cs b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetailArea.cs
index e755924a15..e0a503bc76 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetailArea.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetailArea.cs
@@ -12,10 +12,8 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Beatmap details in song select";
 
-        public override void Reset()
+        public TestCaseBeatmapDetailArea()
         {
-            base.Reset();
-
             Add(new BeatmapDetailArea
             {
                 Anchor = Anchor.Centre,
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetails.cs b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetails.cs
index df80ffdf53..9335938265 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetails.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetails.cs
@@ -13,12 +13,10 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => "BeatmapDetails tab of BeatmapDetailArea";
 
-        private BeatmapDetails details;
+        private readonly BeatmapDetails details;
 
-        public override void Reset()
+        public TestCaseBeatmapDetails()
         {
-            base.Reset();
-
             Add(details = new BeatmapDetails
             {
                 RelativeSizeAxes = Axes.Both,
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapOptionsOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapOptionsOverlay.cs
index 7c211227c6..c9c1740856 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapOptionsOverlay.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapOptionsOverlay.cs
@@ -13,10 +13,8 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Beatmap options in song select";
 
-        public override void Reset()
+        public TestCaseBeatmapOptionsOverlay()
         {
-            base.Reset();
-
             var overlay = new BeatmapOptionsOverlay();
 
             overlay.AddButton(@"Remove", @"from unplayed", FontAwesome.fa_times_circle_o, Color4.Purple, null, Key.Number1);
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseBreadcrumbs.cs b/osu.Desktop.VisualTests/Tests/TestCaseBreadcrumbs.cs
index 658d2f92b1..f2dd454d65 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseBreadcrumbs.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseBreadcrumbs.cs
@@ -11,10 +11,8 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"breadcrumb > control";
 
-        public override void Reset()
+        public TestCaseBreadcrumbs()
         {
-            base.Reset();
-
             BreadcrumbControl<BreadcrumbTab> c;
             Add(c = new BreadcrumbControl<BreadcrumbTab>
             {
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs b/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs
index 2663c952cf..751b979bad 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs
@@ -11,10 +11,8 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Testing chat api and overlay";
 
-        public override void Reset()
+        public TestCaseChatDisplay()
         {
-            base.Reset();
-
             Add(new ChatOverlay
             {
                 State = Visibility.Visible
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs b/osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs
index 808e9b5d19..6c0da885ac 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs
@@ -21,11 +21,9 @@ namespace osu.Desktop.VisualTests.Tests
         private const int start_time = 0;
         private const int duration = 1000;
 
-        private MyContextMenuContainer container;
-
-        public override void Reset()
+        public TestCaseContextMenu()
         {
-            base.Reset();
+            MyContextMenuContainer container;
 
             Add(container = new MyContextMenuContainer
             {
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs
index 90e214c3c9..6924817827 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs
@@ -12,11 +12,9 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Display dialogs";
 
-        private DialogOverlay overlay;
-
-        public override void Reset()
+        public TestCaseDialogOverlay()
         {
-            base.Reset();
+            DialogOverlay overlay;
 
             Add(overlay = new DialogOverlay());
 
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseDirect.cs b/osu.Desktop.VisualTests/Tests/TestCaseDirect.cs
index 4cda14559f..6b68ffa260 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseDirect.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseDirect.cs
@@ -16,9 +16,9 @@ namespace osu.Desktop.VisualTests.Tests
         private DirectOverlay direct;
         private RulesetDatabase rulesets;
 
-        public override void Reset()
+        protected override void LoadComplete()
         {
-            base.Reset();
+            base.LoadComplete();
 
             Add(direct = new DirectOverlay());
             newBeatmaps();
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs b/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs
index 43a8069720..ddda4119bf 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs
@@ -15,9 +15,9 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Select your favourite room";
 
-        public override void Reset()
+        protected override void LoadComplete()
         {
-            base.Reset();
+            base.LoadComplete();
 
             DrawableRoom first;
             DrawableRoom second;
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseDrawings.cs b/osu.Desktop.VisualTests/Tests/TestCaseDrawings.cs
index ebc9930f93..63ec06963c 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseDrawings.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseDrawings.cs
@@ -12,10 +12,8 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => "Tournament drawings";
 
-        public override void Reset()
+        public TestCaseDrawings()
         {
-            base.Reset();
-
             Add(new Drawings
             {
                 TeamList = new TestTeamList(),
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs b/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs
index e2cd2bf67b..00d7e8b5c8 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs
@@ -34,9 +34,9 @@ namespace osu.Desktop.VisualTests.Tests
             this.rulesets = rulesets;
         }
 
-        public override void Reset()
+        protected override void LoadComplete()
         {
-            base.Reset();
+            base.LoadComplete();
 
             List<HitObject> objects = new List<HitObject>();
 
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseGraph.cs b/osu.Desktop.VisualTests/Tests/TestCaseGraph.cs
index f653e2b9b4..d969decaa5 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseGraph.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseGraph.cs
@@ -13,11 +13,9 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => "graph";
 
-        private BarGraph graph;
-
-        public override void Reset()
+        public TestCaseGraph()
         {
-            base.Reset();
+            BarGraph graph;
 
             Children = new[]
             {
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs
index 8c913ae95e..33841cae90 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs
@@ -29,15 +29,58 @@ namespace osu.Desktop.VisualTests.Tests
             var rateAdjustClock = new StopwatchClock(true);
             framedClock = new FramedClock(rateAdjustClock);
             playbackSpeed.ValueChanged += delegate { rateAdjustClock.Rate = playbackSpeed.Value; };
+
+            playbackSpeed.TriggerChange();
+
+            AddStep(@"circles", () => loadHitobjects(HitObjectType.Circle));
+            AddStep(@"slider", () => loadHitobjects(HitObjectType.Slider));
+            AddStep(@"spinner", () => loadHitobjects(HitObjectType.Spinner));
+
+            AddToggleStep(@"auto", state => { auto = state; loadHitobjects(mode); });
+
+            BasicSliderBar<double> sliderBar;
+            Add(new Container
+            {
+                Anchor = Anchor.TopRight,
+                Origin = Anchor.TopRight,
+                AutoSizeAxes = Axes.Both,
+                Children = new Drawable[]
+                {
+                    new SpriteText { Text = "Playback Speed" },
+                    sliderBar = new BasicSliderBar<double>
+                    {
+                        Width = 150,
+                        Height = 10,
+                        SelectionColor = Color4.Orange,
+                    }
+                }
+            });
+
+            sliderBar.Current.BindTo(playbackSpeed);
+
+            framedClock.ProcessFrame();
+
+            var clockAdjustContainer = new Container
+            {
+                RelativeSizeAxes = Axes.Both,
+                Clock = framedClock,
+                Children = new[]
+                {
+                    playfieldContainer = new Container { RelativeSizeAxes = Axes.Both },
+                    approachContainer = new Container { RelativeSizeAxes = Axes.Both }
+                }
+            };
+
+            Add(clockAdjustContainer);
         }
 
         private HitObjectType mode = HitObjectType.Slider;
 
         private readonly BindableNumber<double> playbackSpeed = new BindableDouble(0.5) { MinValue = 0, MaxValue = 1 };
-        private Container playfieldContainer;
-        private Container approachContainer;
+        private readonly Container playfieldContainer;
+        private readonly Container approachContainer;
 
-        private void load(HitObjectType mode)
+        private void loadHitobjects(HitObjectType mode)
         {
             this.mode = mode;
 
@@ -83,54 +126,6 @@ namespace osu.Desktop.VisualTests.Tests
             }
         }
 
-        public override void Reset()
-        {
-            base.Reset();
-
-            playbackSpeed.TriggerChange();
-
-            AddStep(@"circles", () => load(HitObjectType.Circle));
-            AddStep(@"slider", () => load(HitObjectType.Slider));
-            AddStep(@"spinner", () => load(HitObjectType.Spinner));
-
-            AddToggleStep(@"auto", state => { auto = state; load(mode); });
-
-            BasicSliderBar<double> sliderBar;
-            Add(new Container
-            {
-                Anchor = Anchor.TopRight,
-                Origin = Anchor.TopRight,
-                AutoSizeAxes = Axes.Both,
-                Children = new Drawable[]
-                {
-                    new SpriteText { Text = "Playback Speed" },
-                    sliderBar = new BasicSliderBar<double>
-                    {
-                        Width = 150,
-                        Height = 10,
-                        SelectionColor = Color4.Orange,
-                    }
-                }
-            });
-
-            sliderBar.Current.BindTo(playbackSpeed);
-
-            framedClock.ProcessFrame();
-
-            var clockAdjustContainer = new Container
-            {
-                RelativeSizeAxes = Axes.Both,
-                Clock = framedClock,
-                Children = new[]
-                {
-                    playfieldContainer = new Container { RelativeSizeAxes = Axes.Both },
-                    approachContainer = new Container { RelativeSizeAxes = Axes.Both }
-                }
-            };
-
-            Add(clockAdjustContainer);
-        }
-
         private int depth;
 
         private void add(DrawableOsuHitObject h)
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs b/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs
index a28176b512..87a40a76ca 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs
@@ -20,10 +20,8 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Tests key counter";
 
-        public override void Reset()
+        public TestCaseKeyCounter()
         {
-            base.Reset();
-
             KeyCounterCollection kc = new KeyCounterCollection
             {
                 Origin = Anchor.Centre,
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs b/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs
index 39010baf91..12d01ecc79 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs
@@ -16,7 +16,7 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"From song select";
 
-        private Leaderboard leaderboard;
+        private readonly Leaderboard leaderboard;
 
         private void newScores()
         {
@@ -207,10 +207,8 @@ namespace osu.Desktop.VisualTests.Tests
             leaderboard.Scores = scores;
         }
 
-        public override void Reset()
+        public TestCaseLeaderboard()
         {
-            base.Reset();
-
             Add(leaderboard = new Leaderboard
             {
                 Origin = Anchor.Centre,
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseManiaHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseManiaHitObjects.cs
index c66b0b4db4..30346e90c9 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseManiaHitObjects.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseManiaHitObjects.cs
@@ -13,10 +13,8 @@ namespace osu.Desktop.VisualTests.Tests
 {
     internal class TestCaseManiaHitObjects : TestCase
     {
-        public override void Reset()
+        public TestCaseManiaHitObjects()
         {
-            base.Reset();
-
             Add(new FillFlowContainer
             {
                 Anchor = Anchor.Centre,
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs
index 352b6cdc81..adaae91815 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs
@@ -25,10 +25,8 @@ namespace osu.Desktop.VisualTests.Tests
 
         protected override double TimePerAction => 200;
 
-        public override void Reset()
+        public TestCaseManiaPlayfield()
         {
-            base.Reset();
-
             Action<int, SpecialColumnPosition> createPlayfield = (cols, pos) =>
             {
                 Clear();
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs b/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs
index 0caa518a0b..bab471ed6a 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs
@@ -13,10 +13,8 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Main menu button system";
 
-        public override void Reset()
+        public TestCaseMenuButtonSystem()
         {
-            base.Reset();
-
             Add(new Box
             {
                 ColourInfo = ColourInfo.GradientVertical(Color4.Gray, Color4.WhiteSmoke),
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseMenuOverlays.cs b/osu.Desktop.VisualTests/Tests/TestCaseMenuOverlays.cs
index 4de8b297eb..0187c0e629 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseMenuOverlays.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseMenuOverlays.cs
@@ -12,15 +12,12 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Tests pause and fail overlays";
 
-        private PauseContainer.PauseOverlay pauseOverlay;
-        private FailOverlay failOverlay;
-        private int retryCount;
-
-        public override void Reset()
+        public TestCaseMenuOverlays()
         {
-            base.Reset();
+            FailOverlay failOverlay;
+            PauseContainer.PauseOverlay pauseOverlay;
 
-            retryCount = 0;
+            var retryCount = 0;
 
             Add(pauseOverlay = new PauseContainer.PauseOverlay
             {
@@ -34,14 +31,16 @@ namespace osu.Desktop.VisualTests.Tests
                 OnQuit = () => Logger.Log(@"Quit"),
             });
 
-            AddStep(@"Pause", delegate {
+            AddStep(@"Pause", delegate
+            {
                 if (failOverlay.State == Visibility.Visible)
                 {
                     failOverlay.Hide();
                 }
                 pauseOverlay.Show();
             });
-            AddStep("Fail", delegate {
+            AddStep("Fail", delegate
+            {
                 if (pauseOverlay.State == Visibility.Visible)
                 {
                     pauseOverlay.Hide();
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseMods.cs b/osu.Desktop.VisualTests/Tests/TestCaseMods.cs
index 3f3a9d82f5..e626a70e5f 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseMods.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseMods.cs
@@ -27,9 +27,9 @@ namespace osu.Desktop.VisualTests.Tests
             this.rulesets = rulesets;
         }
 
-        public override void Reset()
+        protected override void LoadComplete()
         {
-            base.Reset();
+            base.LoadComplete();
 
             Add(modSelect = new ModSelectOverlay
             {
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseMusicController.cs b/osu.Desktop.VisualTests/Tests/TestCaseMusicController.cs
index 5665bf859a..cbb2775234 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseMusicController.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseMusicController.cs
@@ -13,18 +13,11 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Tests music controller ui.";
 
-        private MusicController mc;
-
         public TestCaseMusicController()
         {
             Clock = new FramedClock();
-        }
 
-        public override void Reset()
-        {
-            base.Reset();
-            Clock.ProcessFrame();
-            mc = new MusicController
+            var mc = new MusicController
             {
                 Origin = Anchor.Centre,
                 Anchor = Anchor.Centre
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs b/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs
index 8972040b06..4ba50c8220 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs
@@ -16,12 +16,10 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"I handle notifications";
 
-        private NotificationManager manager;
+        private readonly NotificationManager manager;
 
-        public override void Reset()
+        public TestCaseNotificationManager()
         {
-            base.Reset();
-
             progressingNotifications.Clear();
 
             Content.Add(manager = new NotificationManager
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseOnScreenDisplay.cs b/osu.Desktop.VisualTests/Tests/TestCaseOnScreenDisplay.cs
index 3cefb8a3d2..f2b4ed7918 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseOnScreenDisplay.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseOnScreenDisplay.cs
@@ -15,9 +15,9 @@ namespace osu.Desktop.VisualTests.Tests
 
         public override string Description => @"Make it easier to see setting changes";
 
-        public override void Reset()
+        protected override void LoadComplete()
         {
-            base.Reset();
+            base.LoadComplete();
 
             Add(new OnScreenDisplay());
 
diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs
index 35eb6d0ff9..83a1436357 100644
--- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs
@@ -13,20 +13,19 @@ namespace osu.Desktop.VisualTests.Tests
 {
     internal class TestCasePlaySongSelect : TestCase
     {
-        private BeatmapDatabase db;
-        private TestStorage storage;
-        private PlaySongSelect songSelect;
+        private readonly BeatmapDatabase db;
 
         public override string Description => @"with fake data";
 
-        private RulesetDatabase rulesets;
+        private readonly RulesetDatabase rulesets;
 
-        public override void Reset()
+        public TestCasePlaySongSelect()
         {
-            base.Reset();
+            PlaySongSelect songSelect;
+
             if (db == null)
             {
-                storage = new TestStorage(@"TestCasePlaySongSelect");
+                var storage = new TestStorage(@"TestCasePlaySongSelect");
 
                 var backingDatabase = storage.GetDatabase(@"client");
 
diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs
index d922f3bb4b..954d24fcc1 100644
--- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs
@@ -2,7 +2,6 @@
 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
 
 using System.Collections.Generic;
-using System.Linq;
 using osu.Framework.Allocation;
 using osu.Framework.Testing;
 using osu.Game.Beatmaps;
@@ -21,65 +20,54 @@ namespace osu.Desktop.VisualTests.Tests
     internal class TestCasePlayer : TestCase
     {
         protected Player Player;
-        private BeatmapDatabase db;
         private RulesetDatabase rulesets;
 
         public override string Description => @"Showing everything to play the game.";
 
         [BackgroundDependencyLoader]
-        private void load(BeatmapDatabase db, RulesetDatabase rulesets)
+        private void load(RulesetDatabase rulesets)
         {
             this.rulesets = rulesets;
-            this.db = db;
         }
 
-        public override void Reset()
+        protected override void LoadComplete()
         {
-            base.Reset();
+            base.LoadComplete();
 
-            WorkingBeatmap beatmap = null;
+            var objects = new List<HitObject>();
 
-            var beatmapInfo = db.Query<BeatmapInfo>().FirstOrDefault(b => b.RulesetID == 0);
-            if (beatmapInfo != null)
-                beatmap = db.GetWorkingBeatmap(beatmapInfo);
-
-            if (beatmap?.Track == null)
+            int time = 1500;
+            for (int i = 0; i < 50; i++)
             {
-                var objects = new List<HitObject>();
-
-                int time = 1500;
-                for (int i = 0; i < 50; i++)
+                objects.Add(new HitCircle
                 {
-                    objects.Add(new HitCircle
-                    {
-                        StartTime = time,
-                        Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : OsuPlayfield.BASE_SIZE.X,
-                        i % 4 < 2 ? 0 : OsuPlayfield.BASE_SIZE.Y),
-                        NewCombo = i % 4 == 0
-                    });
+                    StartTime = time,
+                    Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : OsuPlayfield.BASE_SIZE.X,
+                    i % 4 < 2 ? 0 : OsuPlayfield.BASE_SIZE.Y),
+                    NewCombo = i % 4 == 0
+                });
 
-                    time += 500;
-                }
-
-                Beatmap b = new Beatmap
-                {
-                    HitObjects = objects,
-                    BeatmapInfo = new BeatmapInfo
-                    {
-                        Difficulty = new BeatmapDifficulty(),
-                        Ruleset = rulesets.Query<RulesetInfo>().First(),
-                        Metadata = new BeatmapMetadata
-                        {
-                            Artist = @"Unknown",
-                            Title = @"Sample Beatmap",
-                            Author = @"peppy",
-                        }
-                    }
-                };
-
-                beatmap = new TestWorkingBeatmap(b);
+                time += 500;
             }
 
+            Beatmap b = new Beatmap
+            {
+                HitObjects = objects,
+                BeatmapInfo = new BeatmapInfo
+                {
+                    Difficulty = new BeatmapDifficulty(),
+                    Ruleset = rulesets.Query<RulesetInfo>().First(),
+                    Metadata = new BeatmapMetadata
+                    {
+                        Artist = @"Unknown",
+                        Title = @"Sample Beatmap",
+                        Author = @"peppy",
+                    }
+                }
+            };
+
+            WorkingBeatmap beatmap = new TestWorkingBeatmap(b);
+
             Add(new Box
             {
                 RelativeSizeAxes = Framework.Graphics.Axes.Both,
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseReplaySettingsOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseReplaySettingsOverlay.cs
index b2c211b7f0..00a9774067 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseReplaySettingsOverlay.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseReplaySettingsOverlay.cs
@@ -13,13 +13,11 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Settings visible in replay/auto";
 
-        private ExampleContainer container;
-
-        public override void Reset()
+        public TestCaseReplaySettingsOverlay()
         {
-            base.Reset();
+            ExampleContainer container;
 
-            Add(new ReplaySettingsOverlay()
+            Add(new ReplaySettingsOverlay
             {
                 Anchor = Anchor.TopRight,
                 Origin = Anchor.TopRight,
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseResults.cs b/osu.Desktop.VisualTests/Tests/TestCaseResults.cs
index f8c93e9a73..1cfc2fc664 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseResults.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseResults.cs
@@ -28,9 +28,9 @@ namespace osu.Desktop.VisualTests.Tests
 
         private WorkingBeatmap beatmap;
 
-        public override void Reset()
+        protected override void LoadComplete()
         {
-            base.Reset();
+            base.LoadComplete();
 
             if (beatmap == null)
             {
@@ -39,8 +39,6 @@ namespace osu.Desktop.VisualTests.Tests
                     beatmap = db.GetWorkingBeatmap(beatmapInfo);
             }
 
-            base.Reset();
-
             Add(new Results(new Score
             {
                 TotalScore = 2845370,
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
index beb664e7ff..00702f7ad0 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
@@ -17,9 +17,9 @@ namespace osu.Desktop.VisualTests.Tests
 
         private RulesetDatabase rulesets;
 
-        public override void Reset()
+        protected override void LoadComplete()
         {
-            base.Reset();
+            base.LoadComplete();
 
             var room = new Room
             {
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs b/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs
index 45ae82109f..e8fc2956b4 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs
@@ -15,10 +15,8 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Tests multiple counters";
 
-        public override void Reset()
+        public TestCaseScoreCounter()
         {
-            base.Reset();
-
             int numerator = 0, denominator = 0;
 
             ScoreCounter score = new ScoreCounter(7)
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseScrollingHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseScrollingHitObjects.cs
index 4ddc35eb84..9f439fe193 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseScrollingHitObjects.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseScrollingHitObjects.cs@@ -21,16 +21,15 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => "SpeedAdjustmentContainer/DrawableTimingSection";
 
-        private SpeedAdjustmentCollection adjustmentCollection;
+        private readonly BindableDouble timeRangeBindable;
+        private readonly OsuSpriteText bottomLabel;
+        private readonly SpriteText topTime;
+        private readonly SpriteText bottomTime;
 
-        private BindableDouble timeRangeBindable;
-        private OsuSpriteText timeRangeText;
-        private OsuSpriteText bottomLabel;
-        private SpriteText topTime, bottomTime;
-
-        public override void Reset()
+        public TestCaseScrollingHitObjects()
         {
-            base.Reset();
+            OsuSpriteText timeRangeText;
+            SpeedAdjustmentCollection adjustmentCollection;
 
             timeRangeBindable = new BindableDouble(2000)
             {
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseSettings.cs b/osu.Desktop.VisualTests/Tests/TestCaseSettings.cs
index 660085e558..3d21f0e3b1 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseSettings.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseSettings.cs
@@ -10,13 +10,16 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Tests the settings overlay";
 
-        private SettingsOverlay settings;
+        private readonly SettingsOverlay settings;
 
-        public override void Reset()
+        public TestCaseSettings()
         {
-            base.Reset();
-
             Children = new[] { settings = new SettingsOverlay() };
+        }
+
+        protected override void LoadComplete()
+        {
+            base.LoadComplete();
             settings.ToggleVisibility();
         }
     }
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseSkipButton.cs b/osu.Desktop.VisualTests/Tests/TestCaseSkipButton.cs
index fb5be719c1..1f81226a8e 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseSkipButton.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseSkipButton.cs
@@ -10,9 +10,10 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Skip skip skippediskip";
 
-        public override void Reset()
+        protected override void LoadComplete()
         {
-            base.Reset();
+            base.LoadComplete();
+
             Add(new SkipButton(Clock.CurrentTime + 5000));
         }
     }
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseSocial.cs b/osu.Desktop.VisualTests/Tests/TestCaseSocial.cs
index eb7df96355..34209119bd 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseSocial.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseSocial.cs
@@ -11,10 +11,8 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"social browser overlay";
 
-        public override void Reset()
+        public TestCaseSocial()
         {
-            base.Reset();
-
             SocialOverlay s = new SocialOverlay
             {
                 Users = new[]
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseSongProgress.cs b/osu.Desktop.VisualTests/Tests/TestCaseSongProgress.cs
index e3c343f5f8..3368224be1 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseSongProgress.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseSongProgress.cs
@@ -15,15 +15,13 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"With fake data";
 
-        private SongProgress progress;
-        private SongProgressGraph graph;
+        private readonly SongProgress progress;
+        private readonly SongProgressGraph graph;
 
-        private StopwatchClock clock;
+        private readonly StopwatchClock clock;
 
-        public override void Reset()
+        public TestCaseSongProgress()
         {
-            base.Reset();
-
             clock = new StopwatchClock(true);
 
             Add(progress = new SongProgress
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTabControl.cs b/osu.Desktop.VisualTests/Tests/TestCaseTabControl.cs
index 96933a15e7..c0c01a6daa 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseTabControl.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseTabControl.cs
@@ -14,10 +14,8 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Filter for song select";
 
-        public override void Reset()
+        public TestCaseTabControl()
         {
-            base.Reset();
-
             OsuSpriteText text;
             OsuTabControl<GroupMode> filter;
             Add(filter = new OsuTabControl<GroupMode>
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs
index d769071bd9..d98e39ae7b 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs
@@ -16,10 +16,8 @@ namespace osu.Desktop.VisualTests.Tests
 
         private bool kiai;
 
-        public override void Reset()
+        public TestCaseTaikoHitObjects()
         {
-            base.Reset();
-
             AddToggleStep("Kiai", b =>
             {
                 kiai = !kiai;
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs
index 259d0267db..00929c06c2 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs
@@ -26,13 +26,11 @@ namespace osu.Desktop.VisualTests.Tests
         protected override double TimePerAction => default_duration * 2;
 
         private readonly Random rng = new Random(1337);
-        private TaikoPlayfield playfield;
-        private Container playfieldContainer;
+        private readonly TaikoPlayfield playfield;
+        private readonly Container playfieldContainer;
 
-        public override void Reset()
+        public TestCaseTaikoPlayfield()
         {
-            base.Reset();
-
             AddStep("Hit!", addHitJudgement);
             AddStep("Miss :(", addMissJudgement);
             AddStep("DrumRoll", () => addDrumRoll(false));
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTextAwesome.cs b/osu.Desktop.VisualTests/Tests/TestCaseTextAwesome.cs
index 7182ee7c06..2824c0416f 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseTextAwesome.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseTextAwesome.cs
@@ -16,10 +16,8 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Tests display of icons";
 
-        public override void Reset()
+        public TestCaseTextAwesome()
         {
-            base.Reset();
-
             FillFlowContainer flow;
 
             Add(flow = new FillFlowContainer
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTwoLayerButton.cs b/osu.Desktop.VisualTests/Tests/TestCaseTwoLayerButton.cs
index 2decb4c469..0c35a4b8aa 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseTwoLayerButton.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseTwoLayerButton.cs
@@ -10,10 +10,8 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Mostly back button";
 
-        public override void Reset()
+        public TestCaseTwoLayerButton()
         {
-            base.Reset();
-
             Add(new BackButton());
         }
     }
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseUserPanel.cs b/osu.Desktop.VisualTests/Tests/TestCaseUserPanel.cs
index 92d58c10c9..22cdf42f7d 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseUserPanel.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseUserPanel.cs
@@ -13,10 +13,8 @@ namespace osu.Desktop.VisualTests.Tests
     {
         public override string Description => @"Panels for displaying a user's status";
 
-        public override void Reset()
+        public TestCaseUserPanel()
         {
-            base.Reset();
-
             UserPanel flyte;
             UserPanel peppy;
             Add(new FillFlowContainer
diff --git a/osu.Game/Rulesets/UI/HitRenderer.cs b/osu.Game/Rulesets/UI/HitRenderer.cs
index 00d678e11e..8fe1dd3e0a 100644
--- a/osu.Game/Rulesets/UI/HitRenderer.cs
+++ b/osu.Game/Rulesets/UI/HitRenderer.cs
@@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.UI
 
             // Check if the beatmap can be converted
             if (!converter.CanConvert(beatmap.Beatmap))
-                throw new BeatmapInvalidForRulesetException($"{nameof(Beatmap)} can't be converted for the current ruleset.");
+                throw new BeatmapInvalidForRulesetException($"{nameof(Beatmap)} can not be converted for the current ruleset (converter: {converter}).");
 
             // Convert the beatmap
             Beatmap = converter.Convert(beatmap.Beatmap, isForCurrentRuleset);
diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs
index ea7c465e4d..9251ca33a4 100644
--- a/osu.Game/Screens/Play/SongProgressGraph.cs
+++ b/osu.Game/Screens/Play/SongProgressGraph.cs
@@ -19,6 +19,10 @@ namespace osu.Game.Screens.Play
                 objects = value;
 
                 const int granularity = 200;
+                Values = new int[granularity];
+
+                if (!objects.Any())
+                    return;
 
                 var firstHit = objects.First().StartTime;
                 var lastHit = (objects.Last() as IHasEndTime)?.EndTime ?? 0;
@@ -28,8 +32,6 @@ namespace osu.Game.Screens.Play
 
                 var interval = (lastHit - firstHit + 1) / granularity;
 
-                var values = new int[granularity];
-
                 foreach (var h in objects)
                 {
                     IHasEndTime end = h as IHasEndTime;
@@ -37,10 +39,8 @@ namespace osu.Game.Screens.Play
                     int startRange = (int)((h.StartTime - firstHit) / interval);
                     int endRange = (int)(((end?.EndTime > 0 ? end.EndTime : h.StartTime) - firstHit) / interval);
                     for (int i = startRange; i <= endRange; i++)
-                        values[i]++;
+                        Values[i]++;
                 }
-
-                Values = values;
             }
         }
     }
diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs
index eda3cf39f6..90f18499bf 100644
--- a/osu.Game/Screens/Select/SongSelect.cs
+++ b/osu.Game/Screens/Select/SongSelect.cs
@@ -281,10 +281,13 @@ namespace osu.Game.Screens.Select
         {
             base.Dispose(isDisposing);
 
-            database.BeatmapSetAdded -= onBeatmapSetAdded;
-            database.BeatmapSetRemoved -= onBeatmapSetRemoved;
+            if (database != null)
+            {
+                database.BeatmapSetAdded -= onBeatmapSetAdded;
+                database.BeatmapSetRemoved -= onBeatmapSetRemoved;
+            }
 
-            initialAddSetsTask.Cancel();
+            initialAddSetsTask?.Cancel();
         }
 
         private void changeBackground(WorkingBeatmap beatmap)