diff --git a/Runtime/InteractiveComponent.cs b/Runtime/InteractiveComponent.cs index 8e3d092..4b8e0f4 100644 --- a/Runtime/InteractiveComponent.cs +++ b/Runtime/InteractiveComponent.cs @@ -18,7 +18,7 @@ namespace TestHelper.Monkey /// /// Wrapped component that provide interaction for user. /// - // TODO: Rename to InteractableComponent + [Obsolete] public class InteractiveComponent { /// diff --git a/Runtime/InteractiveComponentCollector.cs b/Runtime/InteractiveComponentCollector.cs index 3641308..b6d6d92 100644 --- a/Runtime/InteractiveComponentCollector.cs +++ b/Runtime/InteractiveComponentCollector.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using System.Linq; using TestHelper.Monkey.DefaultStrategies; +using TestHelper.Monkey.Extensions; using TestHelper.Monkey.Operators; using UnityEngine; using UnityEngine.EventSystems; @@ -47,17 +49,14 @@ public InteractiveComponentCollector( /// /// Note: If you only need UI elements, using UnityEngine.UI.Selectable.allSelectablesArray is faster. /// - /// Interactive components - public IEnumerable FindInteractableComponents() + /// Interactable components + public IEnumerable FindInteractableComponents() { foreach (var component in FindMonoBehaviours()) { if (_isInteractable.Invoke(component)) { - yield return InteractiveComponent.CreateInteractableComponent(component, - _isReachable, - _isInteractable, - _operators); + yield return component; } } } @@ -65,8 +64,7 @@ public IEnumerable FindInteractableComponents() [Obsolete("Use FindInteractableComponents() instead")] public static IEnumerable FindInteractiveComponents() { - var instance = new InteractiveComponentCollector(); - return instance.FindInteractableComponents(); + throw new NotImplementedException("Use FindInteractableComponents() instead"); } /// @@ -75,24 +73,33 @@ public static IEnumerable FindInteractiveComponents() /// /// Note: If you only need UI elements, using UnityEngine.UI.Selectable.allSelectablesArray is faster. /// - /// Really interactive components - public IEnumerable FindReachableInteractableComponents() + /// Reachable and Interactable components + public IEnumerable FindReachableInteractableComponents() { - foreach (var interactiveComponent in FindInteractableComponents()) + foreach (var interactableComponent in FindInteractableComponents()) { - if (_isReachable.Invoke(interactiveComponent.gameObject, _eventData, _results)) + if (_isReachable.Invoke(interactableComponent.gameObject, _eventData, _results)) { - yield return interactiveComponent; + yield return interactableComponent; } } } + /// + /// Returns tuple of interactable component and operator. + /// Note: Not check reachable from user. + /// + /// Tuple of interactable component and operator + public IEnumerable<(Component, IOperator)> FindInteractableComponentsAndOperators() + { + return FindInteractableComponents().SelectMany(x => x.SelectOperators(_operators), (x, o) => (x, o)); + } + [Obsolete("Use FindReachableInteractableComponents() instead")] public static IEnumerable FindReallyInteractiveComponents( Func screenPointStrategy) { - var instance = new InteractiveComponentCollector(); - return instance.FindReachableInteractableComponents(); + throw new NotImplementedException("Use FindReachableInteractableComponents() instead"); } private static IEnumerable FindMonoBehaviours() diff --git a/Runtime/Monkey.cs b/Runtime/Monkey.cs index 1a5759b..c8f7d4f 100644 --- a/Runtime/Monkey.cs +++ b/Runtime/Monkey.cs @@ -7,11 +7,13 @@ using System.Threading; using Cysharp.Threading.Tasks; using TestHelper.Monkey.Annotations; +using TestHelper.Monkey.Extensions; using TestHelper.Monkey.Operators; using TestHelper.Random; using TestHelper.RuntimeInternals; using UnityEngine; using UnityEngine.Assertions; +using UnityEngine.EventSystems; namespace TestHelper.Monkey { @@ -46,7 +48,7 @@ public static async UniTask Run(MonkeyConfig config, CancellationToken cancellat GameViewControlHelper.SetGizmos(true); } - var interactiveComponentCollector = new InteractiveComponentCollector( + var interactableComponentCollector = new InteractiveComponentCollector( isReachable: config.IsReachable, isInteractable: config.IsInteractable, operators: config.Operators); @@ -57,7 +59,13 @@ public static async UniTask Run(MonkeyConfig config, CancellationToken cancellat { while (Time.time < endTime) { - var didAct = await RunStep(config, interactiveComponentCollector, cancellationToken); + var didAct = await RunStep( + config.Random, + config.Logger, + config.Screenshots, + config.IsReachable, + interactableComponentCollector, + cancellationToken); if (didAct) { lastOperationTime = Time.time; @@ -89,23 +97,29 @@ private class CoroutineRunner : MonoBehaviour /// /// Run a step of monkey testing. /// - /// Run configuration for monkey testing - /// + /// Random number generator from MonkeyConfig + /// Logger from MonkeyConfig + /// Take screenshots options from MonkeyConfig + /// Function returns the GameObject is reachable from user or not. from MonkeyConfig + /// InteractableComponentCollector instance includes isReachable, isInteractable, and operators /// Cancellation token - /// + /// True if any operator was executed public static async UniTask RunStep( - MonkeyConfig config, - InteractiveComponentCollector interactiveComponentCollector, + IRandom random, + ILogger logger, + ScreenshotOptions screenshotOptions, + Func, bool> isReachable, + InteractiveComponentCollector interactableComponentCollector, CancellationToken cancellationToken = default) { - var operators = GetOperators(interactiveComponentCollector); - var (selectedComponent, selectedOperator) = LotteryOperator(operators.ToList(), config.Random); + var operators = GetOperators(interactableComponentCollector); + var (selectedComponent, selectedOperator) = LotteryOperator(operators.ToList(), random, isReachable); if (selectedComponent == null || selectedOperator == null) { return false; } - if (config.Screenshots != null) + if (screenshotOptions != null) { if (s_coroutineRunner == null || (bool)s_coroutineRunner == false) { @@ -113,35 +127,32 @@ public static async UniTask RunStep( } await ScreenshotHelper.TakeScreenshot( - directory: config.Screenshots.Directory, - filename: config.Screenshots.FilenameStrategy.GetFilename(), - superSize: config.Screenshots.SuperSize, - stereoCaptureMode: config.Screenshots.StereoCaptureMode + directory: screenshotOptions.Directory, + filename: screenshotOptions.FilenameStrategy.GetFilename(), + superSize: screenshotOptions.SuperSize, + stereoCaptureMode: screenshotOptions.StereoCaptureMode ) .ToUniTask(s_coroutineRunner); } - config.Logger.Log($"{selectedOperator} operates to {selectedComponent.gameObject.name}"); - await selectedOperator.OperateAsync(selectedComponent.component, cancellationToken); + logger.Log($"{selectedOperator} operates to {selectedComponent.gameObject.name}"); + await selectedOperator.OperateAsync(selectedComponent, cancellationToken); return true; } - internal static IEnumerable<(InteractiveComponent, IOperator)> GetOperators( - InteractiveComponentCollector interactiveComponentCollector) + internal static IEnumerable<(Component, IOperator)> GetOperators(InteractiveComponentCollector collector) { - var components = interactiveComponentCollector.FindInteractableComponents() - .Where(x => !x.gameObject.TryGetComponent(typeof(IgnoreAnnotation), out _)); - return components.SelectMany(x => x.GetOperators(), (x, o) => (x, o)); + return collector.FindInteractableComponentsAndOperators() + .Where(x => !x.Item1.gameObject.TryGetComponent(typeof(IgnoreAnnotation), out _)); } - internal static (InteractiveComponent, IOperator) LotteryOperator( - List<(InteractiveComponent, IOperator)> operators, - IRandom random) + internal static (Component, IOperator) LotteryOperator(List<(Component, IOperator)> operators, IRandom random, + Func, bool> isReachable) { while (operators.Count > 0) { var (selectedComponent, selectedOperator) = operators[random.Next(operators.Count)]; - if (selectedComponent.IsReachable()) + if (selectedComponent.gameObject.IsReachable(isReachable)) { return (selectedComponent, selectedOperator); } diff --git a/Samples~/uGUI Demo/Tests/Runtime/ScenarioTest.cs b/Samples~/uGUI Demo/Tests/Runtime/ScenarioTest.cs index 1410c1a..3cf91ef 100644 --- a/Samples~/uGUI Demo/Tests/Runtime/ScenarioTest.cs +++ b/Samples~/uGUI Demo/Tests/Runtime/ScenarioTest.cs @@ -5,9 +5,8 @@ using System.Threading.Tasks; using NUnit.Framework; using TestHelper.Attributes; +using TestHelper.Monkey.Extensions; using TestHelper.Monkey.Operators; -using UnityEngine; -using UnityEngine.UI; namespace TestHelper.Monkey.Samples.UGUIDemo { @@ -30,32 +29,27 @@ public async Task OpenSubScreens(string target) // When click Start button, then open Home screen. var startButton = await _finder.FindByNameAsync("StartButton", interactable: true); - var startComponent = CreateInteractableComponent(startButton.GetComponent