xamarin - 如何在 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);
}
}
}
}
}
}
解决方案
你不需要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);
推荐阅读
- unix - 如何在 Unix 的 head 和 tail 之间添加换行符?
- sqlite - 如何在一个 sql 表中加入所有内容并从另一个表中第一次出现,保留所有来自第一个表
- python - tensorflow 数据集在过滤后无法计算出 epoch 中的训练步数
- android - 当我收到意图时额外丢失
- c++ - 如何在我的 C++ 程序中链接和使用远程 cplex
- java - 单例 bean 是否与 Spring 中的所有用户共享数据?
- python-3.x - 如何将 def common_stats 集成到类 Data_Load 中?
- flutter - 如何在 Flutter 中将字符串转换为对象?
- reactjs - 如何在鼠标悬停的情况下显示/隐藏antd卡中的额外部分?
- python - 在 python 虚拟环境中 AWS S3 访问被拒绝