···11+// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
22+// See the LICENCE file in the repository root for full licence text.
33+44+using System;
55+using JetBrains.Annotations;
66+77+namespace osu.Framework.Testing
88+{
99+ /// <summary>
1010+ /// Denotes a "visual" test which should only be run in a headless context.
1111+ /// This will stop the test from showing up in a <see cref="TestBrowser"/>.
1212+ /// </summary>
1313+ [AttributeUsage(AttributeTargets.Class)]
1414+ [MeansImplicitUse]
1515+ public class HeadlessTestAttribute : Attribute
1616+ {
1717+ }
1818+}
+3-1
osu.Framework/Testing/TestBrowser.cs
···6363 //we want to build the lists here because we're interested in the assembly we were *created* on.
6464 foreach (Assembly asm in assemblies.ToList())
6565 {
6666- var tests = asm.GetLoadableTypes().Where(t => t.IsSubclassOf(typeof(TestScene)) && !t.IsAbstract && t.IsPublic).ToList();
6666+ var tests = asm.GetLoadableTypes().Where(isValidVisualTest).ToList();
67676868 if (!tests.Any())
6969 {
···77777878 TestTypes.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));
7979 }
8080+8181+ private bool isValidVisualTest(Type t) => t.IsSubclassOf(typeof(TestScene)) && !t.IsAbstract && t.IsPublic && !t.GetCustomAttributes<HeadlessTestAttribute>().Any();
80828183 private void updateList(ValueChangedEvent<Assembly> args)
8284 {