Skip to content

Creating Your First Test

David O'Donoghue edited this page Feb 5, 2026 · 5 revisions

Creating Your First Test

Step-by-step guide to creating and running your first UIAutomation test.

Test Structure

UIAutomation tests use Unity's standard NUnit test framework with async/await:

using System.Threading.Tasks;
using NUnit.Framework;
using UnityEngine.TestTools;
using static ODDGames.UIAutomation.ActionExecutor;

[TestFixture]
public class MyTests
{
    [Test]
    public async Task MyFirstTest()
    {
        await LoadScene("MainMenuScene");
        await Click(Name("PlayButton"));
        await WaitFor(Name("GameScene"), seconds: 5);
    }
}

Understanding using static

The using static ODDGames.UIAutomation.ActionExecutor; directive imports all static members directly into your test class. This means you can write:

// With 'using static' - clean and readable
await Click(Name("Button"));
await TextInput(Adjacent("Username:"), "test");
await WaitFor(Text("Welcome"), seconds: 5);

Instead of:

// Without 'using static' - verbose
await ActionExecutor.Click(ActionExecutor.Name("Button"));
await ActionExecutor.TextInput(ActionExecutor.Adjacent("Username:"), "test");
await ActionExecutor.WaitFor(ActionExecutor.Text("Welcome"), seconds: 5);

The static import gives you direct access to:

  • Search helpers: Name(), Text(), Type<T>(), Adjacent(), Near(), Path(), Tag(), Texture(), Any(), Reflect()
  • Actions: Click(), DoubleClick(), Hold(), TextInput(), Drag(), DragTo(), Swipe(), Scroll()
  • Waits: Wait(), WaitFor(), WaitFramerate()
  • Finders: Find<T>(), FindAll<T>(), ScrollTo()
  • Scene: LoadScene()

1. Create the Test Script

Create a new C# script in your project's Assets/Tests/PlayMode/ folder:

using System.Threading.Tasks;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using static ODDGames.UIAutomation.ActionExecutor;

[TestFixture]
public class MyFirstTests
{
    [Test]
    public async Task MyFirstTest()
    {
        Debug.Log("Test started!");
        await Wait(seconds: 1);
        Debug.Log("Test completed!");
    }
}

2. Set Up Test Assembly

Ensure you have a test assembly definition:

  1. Create Assets/Tests/PlayMode/Tests.asmdef
  2. Configure it to reference:
    • ODDGames.UIAutomation
    • UnityEngine.TestRunner
    • nunit.framework

3. Run the Test

  1. Open Window > General > Test Runner
  2. Select PlayMode tab
  3. Click Run All or select your test and click Run Selected

Basic Test Example

Here's a simple test that navigates a menu:

[TestFixture]
public class NavigationTests
{
    [Test]
    public async Task UserCanAccessSettings()
    {
        await LoadScene("MainMenuScene");

        // Click the Settings button
        await Click(Name("SettingsButton"));

        // Wait for Settings panel to appear
        await WaitFor(Name("SettingsPanel"), seconds: 5);

        // Click Back to return
        await Click(Name("BackButton"));

        // Verify we're back at main menu
        await WaitFor(Name("MainMenu"), seconds: 5);
    }
}

Form Input Example

Test that fills out a form:

[TestFixture]
public class FormTests
{
    [Test]
    public async Task UserCanSubmitContactForm()
    {
        await LoadScene("ContactScene");

        // Navigate to form
        await Click(Name("ContactUsButton"));

        // Fill out fields using adjacent labels
        await TextInput(Adjacent("Name:"), "John Doe");
        await TextInput(Adjacent("Email:"), "john@example.com");
        await TextInput(Adjacent("Message:"), "Hello world!");

        // Submit
        await Click(Name("SendButton"));

        // Verify success
        await WaitFor(Text("Message sent!"), seconds: 10);
    }
}

Test Structure Best Practices

1. Clear Test Names

Use descriptive names that explain the scenario:

[Test]
public async Task Login_WithValidCredentials_ShowsMainMenu() { }

[Test]
public async Task Login_WithInvalidPassword_ShowsErrorMessage() { }

2. One Scenario Per Test

Keep tests focused on a single user flow:

// Good - single focused scenarios
public async Task AddItemToCart_IncreasesCartCount() { }
public async Task RemoveItemFromCart_DecreasesCartCount() { }
public async Task Checkout_WithEmptyCart_ShowsWarning() { }

// Avoid - multiple scenarios in one test
public async Task CartTests() { }  // Does too many things

3. Use Wait for Async UI

Always wait for UI elements before interacting:

// Good
await Click(Name("OpenDialogButton"));
await WaitFor(Name("Dialog"), seconds: 5);
await Click(Name("ConfirmButton"));

// Risky - dialog might not be ready
await Click(Name("OpenDialogButton"));
await Click(Name("ConfirmButton"));  // May fail if dialog hasn't appeared

Setup and Teardown

Use NUnit's setup attributes for common setup:

[TestFixture]
public class GameplayTests
{
    [SetUp]
    public void SetUp()
    {
        // Reset game state before each test
        PlayerPrefs.DeleteAll();
    }

    [TearDown]
    public void TearDown()
    {
        // Clean up after each test
    }

    [Test]
    public async Task SomeTest()
    {
        await LoadScene("GameScene");
        // Test code...
    }
}

Debugging Tests

Add logging to understand test flow:

[Test]
public async Task LoginTest()
{
    Debug.Log("Starting login test");

    await Click(Name("LoginButton"));
    Debug.Log("Clicked login button");

    await TextInput(Adjacent("Username:"), "testuser");
    Debug.Log("Entered username");

    // ...
}

Next Steps

Clone this wiki locally