如何在Xamarin Forms应用中的TabbedPage栏项上设置AutomationId以进行UI测试

时间:2019-01-28 20:06:53

标签: xamarin xamarin.forms xamarin.ios xamarin.android xamarin.uitest

我正在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);
                    }
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:2)

您不需要CustomRenderer。您只需要将AutomationId设置为TabPage的子项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中使用相同的资源集作为测试的一部分。

app.Tap(AppResources.MyMainTabText)