首页 > 解决方案 > 如何在 Xamarin Forms 应用程序中的 TabbedPage 栏项上设置 AutomationId 以进行 UI 测试

问题描述

我正在 Xamarin UI 测试中为基于选项卡的 Xamarin Forms 应用程序编写测试。我想在每个选项卡项上设置自动化 ID,以便我的 UI 测试可以单击特定选项卡,而无需参考已本地化的选项卡的文本标签。

我想您需要使用自定义渲染器并设置 ContentDescription (Android) 和 AccessibilityIdentifier (iOS),我一直在尝试这样做,但结果好坏参半。这样做的正确方法是什么?如果我使用自定义渲染器走在正确的轨道上,我应该在 IOS/Android 中覆盖哪个渲染器方法来实现这一点?

更新:

iOS: 答案由@apineda 提供。在问题下方查看他的解决方案。

Android:似乎需要自定义渲染器。这有点恶心,但它有效。我们必须递归搜索选项卡栏项目的视图层次结构并为每个设置“ContentDescription”。由于我们使用的是底部导航栏,因此我们向后搜索以获得更好的性能。对于顶部导航栏,您需要搜索“TabLayout”而不是“BottomNavigationItemView”。

[assembly: ExportRenderer(typeof(MainPage), typeof(CustomTabbedPageRenderer))]
namespace Company.Project.Droid.CustomRenderers
{
    public class CustomTabbedPageRenderer : TabbedRenderer
    {
        private bool tabsSet = false;

        public CustomTabbedPageRenderer(Context context)
            : base(context)
        {

        }

        protected override void DispatchDraw(Canvas canvas)
        {
            if (!tabsSet)
            {
                SetTabsContentDescription(this);
            }

            base.DispatchDraw(canvas);
        }

        private void SetTabsContentDescription(Android.Views.ViewGroup viewGroup)
        {
            if (tabsSet)
            {
                return;
            }

            // loop through the view hierarchy backwards. this will work faster since the tab bar
            // is at the bottom of the page
            for (int i = viewGroup.ChildCount -1; i >= 0; i--)
            {
                var menuItem = viewGroup.GetChildAt(i) as BottomNavigationItemView;

                if (menuItem != null)
                {
                    menuItem.ContentDescription = "TabBarItem" + i.ToString();

                    // mark the tabs as set, so we don't do this loop again
                    tabsSet = true;
                }
                else
                {
                    var viewGroupChild = viewGroup.GetChildAt(i) as Android.Views.ViewGroup;
                    if (viewGroupChild != null && viewGroupChild.ChildCount > 0)
                    {
                        SetTabsContentDescription(viewGroupChild);
                    }
                }
            }
        }
    }
}

标签: xamarinxamarin.formsxamarin.iosxamarin.androidxamarin.uitest

解决方案


你不需要CustomRenderer这个。您只需将 设置为TabPageAutomationId的子Pages项,并将其分配给栏项。

假设你有这个TabPage如下

<?xml version="1.0" encoding="UTF-8"?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                xmlns:local="clr-namespace:MyGreatNamespace"
             x:Class="MyGreatNamespace.MyTabPage">
    <TabbedPage.Children>
         <local:MainPage AutomationId="MainTab" Title="Main Page" />
         <local:PageOne AutomationId="TabOne" Title="Page One" />
         <local:PageTwo AutomationId="TabTwo" Title="Page Two" />
    </TabbedPage.Children>
</TabbedPage>

使用此配置,您将能够:

app.Tap("TabTwo");

而且您不需要使用该Text属性。

希望这可以帮助。-

更新:

刚刚确认上述内容不适用于 Android(注意到您最初的问题是针对 Android 的),但仅适用于 iOS。由于某种原因,行为是不同的。

您仍然可以使用文本的本地化版本来“点击它”,如下所述。

处理本地化文本时可以使用的一个技巧是设置正确的文化,然后使用 XAML 中设置的相同资源作为测试的一部分。

IE

app.Tap(AppResources.MyMainTabText);

推荐阅读