[UnityTest] Simulate keyboard input with the new Input System

Hi,

I’m adding UnitTest to my project and now I’m trying to simulate interaction with the UI, but I can’t figure out how I can simulate pressing a key from a keyboard.
I’ve tried several ways but I can’t get it to work.

    [UnityTest]
            public IEnumerator Write_Text_Into_Selected_Input_Field()
            {
                //ARRANGE
                yield return Click_InputField_With_Touch();
                TMP_InputField inputField = Object.FindObjectOfType<TMP_InputField>();

                var keyboard = InputSystem.AddDevice<Keyboard>();
                SetKeyboardLayout("QWERTY", keyboard);
                string text = "qwerty";
    
                //ACT

                //First try
                Click(keyboard.qKey);
                yield return null;
                Click(keyboard.wKey);
                yield return null;
                Click(keyboard.eKey);
                yield return null;
                Click(keyboard.rKey);
                yield return null;
                Click(keyboard.tKey);
                yield return null;
                Click(keyboard.yKey);
                yield return null;

                //Second try
                Set(keyboard.qKey, 1f);
                yield return null;
                Set(keyboard.wKey, 1f);
                yield return null;
                Set(keyboard.eKey, 1f);
                yield return null;
                Set(keyboard.rKey, 1f);
                yield return null;
                Set(keyboard.tKey, 1f);
                yield return null;
                Set(keyboard.yKey, 1f);
                yield return null;

                //Third try
                foreach (char item in text)
                {
                    KeyUtility.charToKey.TryGetValue(char.ToLower(keyChar), out Key key);
                    InputSystem.QueueStateEvent(keyboard, new KeyboardState(key));
                    InputSystem.Update();
                    yield return null;
                }
    
                //ASSERT
                Assert.AreEqual(text, inputField.text);
            }

1 Answer

1

@Michele_Santoni - Unfortunately, the Unity Input System’s built-in keyboard simulation can be a bit tricky to work with. However, you’re on the right track. I would suggest a minor change to your third approach.

Rather than directly calling InputSystem.QueueStateEvent, you can use Press and Release methods from the Keyboard class. This way, you’re ensuring the input system processes the key press and key release events as if they were happening in real-time. You can try something like this, but im unsure if it will work, so your milage may vary:

[UnityTest]
public IEnumerator Write_Text_Into_Selected_Input_Field()
{
    //ARRANGE
    yield return Click_InputField_With_Touch();
    TMP_InputField inputField = Object.FindObjectOfType<TMP_InputField>();

    var keyboard = InputSystem.AddDevice<Keyboard>();
    SetKeyboardLayout("QWERTY", keyboard);
    string text = "qwerty";

    //ACT
    foreach (char c in text)
    {
        Key key = (Key)System.Enum.Parse(typeof(Key), c.ToString().ToUpper());
        Press(keyboard[key]);
        yield return null;
        Release(keyboard[key]);
        yield return null;
    }

    //ASSERT
    Assert.AreEqual(text, inputField.text);
}

In this code, for each character in your text string, you’re parsing the uppercase version of the character into the Key enum. Then, you’re using the Press and Release methods to simulate the key press and release events. You’re yielding after each key press and release to ensure that Unity processes the events.