首页 > 解决方案 > 使用 Xamarin UITest 在 iOS 选取器中选择一个项目?

问题描述

我们正在使用 UITest 测试我们的 Xamarin.Forms 应用,并且需要在 iOS 上选择 Picker 的值。

可以通过这样的项目集合中的行号进行选择:

app.Query(x => x.Class("UIPickerView").Invoke("selectRow", 1, "inComponent", 0, "animated", true))

我们在上面的例子中选择了第 1 行。

但是,我们需要能够按值进行选择 - 例如,对于具有标题列表的 Picker,要选择“Mrs”标题,我们需要执行以下操作:

app.Query(x => x.Class("UIPickerView").Invoke("selectValue", "Mrs", "inComponent", 0, "animated", true))

但是,UIPickerView 上没有可用的 selectValue(或类似)方法(参考此处)。

一种想法是获取项目中的行数,并遍历它们 - 但是当我尝试调用时getNumberOfRows,我收到以下错误:

app.Query(x => x.Class("UIPickerView").Invoke("numberOfRows", "inComponent", 0))

执行 Query([unknown]) 异常时出错:System.Exception:调用 iOS 选择器需要 0 个或奇数个参数(它们必须成对匹配,包括方法名称)。在 Xamarin.UITest.Queries.InvokeHelper.AppTypedSelector (Xamarin.UITest.Queries.AppQuery appQuery, Xamarin.UITest.Queries.ITokenContainer tokenContainer, System.Object[] queryParams, System.String methodName, System.Object[] arguments, System. Boolean explicitRequestedValue) [0x0011a] in <2a16c16730a54859bda72c6bc1c728f7>:0 在 Xamarin.UITest.Queries.InvokeHelper.Invoke (Xamarin.UITest.Queries.AppQuery appQuery, System.String methodName, System.Object[] arguments) [0x00000] in <2a16c16730bc154 >:0 在 Xamarin.UITest.Queries.AppQuery.Invoke (System.String methodName, System.Object arg1,2[T,TResult] typedQuery) [0x0000c] in <2a16c16730a54859bda72c6bc1c728f7>:0 at Xamarin.UITest.iOS.iOSApp+<>c__DisplayClass17_01[T].b__0 () [0x00000] in <2a16c16730a54859bda72c6bc1c728f7>:0 在 Xamarin.UITest.Utils.ErrorReporting.With[T] (System.Func`1[TResult] func, System.Object[] args, System. String memberName) [0x0000e] in <2a16c16730a54859bda72c6bc1c728f7>:0 异常:执行查询时出错([未知])

错误的原因很清楚 - 该方法需要特定的参数对,但我看不出如何正确地制定查询。

那么关于如何按值而不是行号和/或如何获取项目数的任何想法/指针?

标签: iospickerxamarin.uitest

解决方案


更好的解决方案是写一个UITest后门,然后在后门中找到Picker的Renderer,直接控制。

@LandLu 在 Xamarin 论坛上向我提供了解决方案的核心:

您应该首先获取当前视图控制器。然后迭代子视图以获取您的选择器渲染器。这是我的依赖服务,供您参考:

[assembly: Dependency(typeof(FindViewClass))]
namespace Demo.iOS
{
    public class FindViewClass : IFindView
    {
        public void FindViewOfClass()
        {
            UIViewController currentViewController = topViewController();
            getView(currentViewController.View);
        }

        List<PickerRenderer> pickerList = new List<PickerRenderer>();
        void getView(UIView view)
        {
            if (view is PickerRenderer)
            {
                pickerList.Add((PickerRenderer)view);
            }
            else
            {
                foreach (UIView subView in view.Subviews)
                {
                    getView(subView);
                }               
            }
        }

        UIViewController topViewController()
        {
            return topViewControllerWithRootViewController(UIApplication.SharedApplication.KeyWindow.RootViewController);
        }

        UIViewController topViewControllerWithRootViewController(UIViewController rootViewController)
        {
            if (rootViewController is UITabBarController)
            {
                UITabBarController tabbarController = (UITabBarController)rootViewController;
                return topViewControllerWithRootViewController(tabbarController.SelectedViewController);
            }
            else if (rootViewController is UINavigationController)
            {
                UINavigationController navigationController = (UINavigationController)rootViewController;
                return topViewControllerWithRootViewController(navigationController.VisibleViewController);
            }
            else if (rootViewController.PresentedViewController != null)
            {
                UIViewController presentedViewController = rootViewController.PresentedViewController;
                return topViewControllerWithRootViewController(presentedViewController);
            }
            return rootViewController;
        }
    }
}

完成后,我可以通过渲染器的 Element 属性选择我想要的索引/项目。

编辑 我已经把它处理成一个GitHub 存储库,它实现了一组后门,使 iOS 选择器选择更容易


推荐阅读