Repository navigation
Test Attributes
Bugpunch tests are standard NUnit tests, so you organise and annotate them with NUnit's own attributes. The SDK adds one attribute of its own, [BugpunchTestReset], for resetting game state between automated runs.
Earlier versions documented a
[UITest(Feature, Story, Severity, …)]attribute and aTestSeverityenum. Neither ships in the current package; use the NUnit equivalents below.
| Need | NUnit attribute |
|---|---|
| Feature area / filtering | [Category("Authentication")] |
| Description of what is validated | [Description("Valid credentials reach the main menu")] |
| Arbitrary key/value metadata (story, owner, severity) | [Property("Story", "User can log in")] |
| Maximum duration |
[Timeout(180000)] (milliseconds) |
| Run order within a fixture | [Order(1)] |
| Skip a test | [Ignore("Reason")] |
UnityEngine also defines a PropertyAttribute, so in a file that imports both namespaces add an alias for NUnit's:
using System.Threading.Tasks;
using NUnit.Framework;
using UnityEngine;
using Property = NUnit.Framework.PropertyAttribute;
using static ODDGames.BugpunchSdk.ActionExecutor;
[TestFixture]
[Category("Authentication")]
[Property("Owner", "qa-team")]
public class LoginTests
{
[Test]
[Description("Valid credentials reach the main menu")]
[Property("Story", "User can log in")]
[Property("Severity", "Critical")]
[Timeout(180000)]
public async Task Login_WithValidCredentials_ShowsMainMenu()
{
await TextInput(Adjacent("Username:"), "testuser");
await TextInput(Adjacent("Password:"), "password");
await Click(Text("Login"));
await WaitFor(Name("MainMenu"));
}
}The Test Runner window's category dropdown filters by [Category]. From the command line, pass -testCategory:
Unity -batchmode -projectPath . -runTests -testPlatform PlayMode -testCategory "Authentication;Shopping"
Group tests by feature with one category per fixture, and add extra categories ("slow", "nightly", "requires-server") for scheduling:
using NUnit.Framework;
[TestFixture, Category("Performance"), Category("nightly")]
public class LongRunningTests { }
[TestFixture, Category("Integration"), Category("requires-server")]
public class NetworkTests { }NUnit exposes the current test's properties through TestContext:
var props = TestContext.CurrentContext.Test.Properties;
var story = props.Get("Story") as string;
var categories = props["Category"];
Debug.Log($"Running '{TestContext.CurrentContext.Test.Name}' story={story}");Mark a static method in your game code with [BugpunchTestReset] to have it called when an automated run asks the game to reset its state — for example clearing saves, scores or singletons:
using UnityEngine;
using ODDGames.BugpunchSdk;
public static class GameTestHooks
{
[BugpunchTestReset]
public static void ResetForTest()
{
PlayerPrefs.DeleteAll();
}
}The SDK invokes every [BugpunchTestReset] method it finds in the loaded assemblies when a connected Remote IDE / test runner sends POST /test/reset to the device. It is not called automatically by NUnit; in a local NUnit test, call your reset method from [SetUp] directly.
using NUnit.Framework;
// Good - one spelling everywhere
[TestFixture, Category("User Profile")] public class ProfileEditTests { }
[TestFixture, Category("User Profile")] public class ProfilePictureTests { }
// Avoid - three spellings of the same area make filtering unreliable
[TestFixture, Category("UserProfile")] public class ProfileSettingsTests { }
[TestFixture, Category("Profile")] public class ProfileStatsTests { }The method name is what the Test Runner shows first — make it describe the user goal:
// Good - describes the scenario and outcome
[Test] public async Task Profile_UploadPicture_ShowsNewAvatar() { }
// Avoid - says nothing about what failed
[Test] public async Task ProfileTest1() { }Basic Filters
Proximity
Hierarchy
Spatial
Ordering
Modifiers
Combining
Reflection
- Test Actions
- Click Actions
- Text Input
- Drag Actions
- Gesture Input
- Wait and Find
- Assertions
- GameObject Manipulation