ホームページ  >  記事  >  ウェブフロントエンド  >  Selenium を使用してグローバル testing_html/css_WEB-ITnose で Web 要素を見つける際の困難の分析

Selenium を使用してグローバル testing_html/css_WEB-ITnose で Web 要素を見つける際の困難の分析

WBOY
WBOYオリジナル
2016-06-24 11:20:291258ブラウズ

翻訳検証テストで Web 要素を見つける際の課題

翻訳検証テストはグローバリゼーション テストの一部であり、ソフトウェア ユーザー インターフェイスで翻訳する必要がある文字列が正しく翻訳されているかどうかを検証するように設計されています。効率を向上させるために、テスト ケースは通常、製品に精通したテスト サポート エンジニアによって作成され、その後、さまざまな国の言語に精通したテスターに​​よってテスト ケースが実行されます。または、テスト サポート エンジニアが最初に実行します。各言語環境での複雑なユースケースの実行結果のスクリーンショットが作成され、両方のモードが検証のためにテスターに​​送信されます。継続的デリバリー モデルの出現により、テスト担当者が複数言語環境でユース ケースを繰り返し実行したり、テスト サポート エンジニアが複数言語環境でスクリーンショットを手動で取得して継続的デリバリーの速度要件を満たすことが困難になりました。複数言語のタスクを完了するための自動スクリプトを作成する環境での自動スクリーンショットは、効率を向上させるために避けられない選択肢となっています。

従来の Web 自動テスト アプリケーションのシナリオでは、プログラムのコーディングが不規則であるため、静的な ID や名前を使用して要素を直接見つけることは通常困難でしたが、幸いなことに、CSS セレクターと XPath の配置によって新しい可能性が得られました。しかし、DHTML と Ajax の普及により、Dojo などのクライアント スクリプトによって生成される DOM 構造は非常に複雑になり、複数のページの DOM サブノードが存在する可能性があります。 DOM ツリー、および要素の ID は動的です (ID は通常、接頭辞と動的番号で構成されます。接頭辞は要素に対応するコンポーネントのタイプを示し、番号は DOM 上のウィジェットの位置によって決まります)実行時のツリー)。その結果、一部の要素では、CSS 疑似クラスに依存し、セレクターを組み合わせて使用​​することによって、正確な位置決めが必要になることもあります。翻訳検証テストの自動化の場合、この問題は特に顕著です。これは、翻訳検証テストの自動化されたスクリプトが「一度作成すれば、複数の言語環境で実行できる」という要件があり、要素の配置における最後の「救命のわら」である CSS によるものです。疑似クラスでのインライン テキスト マッチングも、そのままでは機能しません。

以下では、読者が上記のさまざまな課題に対処するために柔軟に使用できることを期待して、著者は例を通じて要素の配置方法について詳しく説明します。

Selenium IDE と WebDriver の配置要素の概要

Selenium は、Web インターフェイスのテストを自動化するために使用できる強力なブラウザ自動化ツールです。さまざまな実装原理と使用方法に従って、Selenium IDE と WebDriver に分けられます。前者はユーザーにブラウザ プラグインの形式で簡単かつ迅速に自動スクリプトを作成する機能を提供し、後者はユーザーにより柔軟な機能を提供します。 API ライブラリの形式による柔軟性。堅牢な Web オートメーション機能。

Selenium IDE は、位置決めのためにコマンドで locatorType=location の形式を使用します。通常、WebDriver は findElement(By.locatorType("value") または findElements を使用して、条件に一致する最初の要素を見つけます。 (By.locatorType("value") 関数は要素を検索します。前者は一意の要素を返し、後者は要素のリストを返します。特定の配置は By.locatorType("value") によって実装されます。使用される位置決め メソッドに関して言えば、どちらも基本的に locatorType によって位置決めされます。一般的に使用される locatorType には、id、name、リンク テキスト、dom/JavaScript、xpath、css などが含まれます。例については、リスト 2 を参照してください (末尾の括弧内の数字)。この行は、現在の行の位置を示しています (ブラウザーがリスト 1 HTML ドキュメント内の要素のどの行を検索するかを示します):

リスト 1. HTML の例 1

(01)<html> (02) <body> (03) <form id="loginForm" name="loginFrom"> (04) <input class="required" name="username" type="text" /> (05) <input class="required passfield" name="password" type="password" /> (06) <input name="continue" type="submit" value="Login" /> (07) <input name="continue" type="button" value="Clear" /> (08) </form> (09) <p>Are you sure you want to do this?</p> (10) <a href="continue.html">Continue</a> (11) <a href="cancel.html">Cancel</a> (12)</body> (13)<html>

リスト 2. Selenium と WebDriver の一般的な配置方法

//by IDid=loginForm(03)//in IDEWebElement element = driver.findElement(By.id("loginForm"));(03)//in WebDriver//by Namename=continue type=button(07)//in IDEWebElement element = driver.findElement(By.name("loginForm"));(03)//in WebDriver//by link textlink=Continue(10)//in IDEWebElement element = driver.findElement(By.linkText("Continue"));(10)//in WebDriver//by DOM or JavaScriptdom=document.forms[0].elements['username'](04)//use DOM in IDEWebElement element = (WebElement) ((JavascriptExecutor)driver).                       executeScript("return $('.required')[0]"); (04)//use JQuery in WebDriver //by XPath//form[@id='loginForm']/input[1](04)//by IDEWebElement element = driver.findElement(By.xpath("//input[@name='username']"));(04)//by WebDriver//by CSScss=#loginForm input[type="password"](05)//by IDEWebElement e = driver.findElement(By.cssSelector("input.passfield")(05)//by WebDriver

ID による配置and name は最も効率的で推奨される配置方法ですが、名前は必ずしも一意ではないため、配置中に条件に一致する複数の要素が存在する可能性があります。そのため、この場合、条件に一致する最初の要素のみが配置されます (または、複数の要素が存在する場合)。要素は同じ名前を持ちます)。リンク テキスト) 属性の場合、IDE が位置決めに名前を使用するリスト 2 の例のように、正確な位置決めを行うには追加のフィルターが必要です。

DOM は HTML ドキュメント全体の構造を表します。 DOM 構造に基づいて、Selenium IDE は JavaScript のドット演算子を使用して階層的な位置決めを行うことができ、DOM ロケーターのみが「document」で始まるため、「dom=」も使用できます。さらに、WebDriver では、要素を見つけるための DOM オブジェクトの JavaScript ステートメントを実行することもできます。たとえば、リスト 2 では、WebDriver は JQuery (JavaScript フレームワーク) の要素検索関数 $ を使用します。 ) 位置決め用。

XPath 最初是用来在 XML 文档中定位 DOM 节点的语言,由于 HTML 也可以算作 XML 的一种实现,所以 Selenium 也可以利用 XPath 这一强大的语言来定位 Web 元素。XPath 在传统属性定位之外扩展了诸如“定位第三个多选框”等定位能力,以便应对没有 ID 或 name 属性的情况。利用 Xpath 可以通过绝对路径,或者相对于一个可精确定位的元素的相对路径来定位。为了保证定位的健壮性,推荐使用相对路径和基于位置关系的定位。同样由于只有 XPath 定位器以“//”开头,所以“xpath=”也可以省略。

CSS (Cascading Style Sheets) 是一种用于渲染 HTML 或者 XML 文档的语言,CSS 利用其选择器可以将样式属性绑定到文档中的指定元素,即前端开发人员可以利用 CSS 设定页面上每一个元素的样式。所以理论上说无论一个元素定位有多复杂,既然开发人员能够定位到并设置样式,那么测试人员同样应该也能定位继而操作该元素。这也正是 Selenium 官方极力推荐使用 CSS 定位,而不是 XPath 定位的主要原因。CSS 定位被推崇的另一个原因是不同的浏览器 XPath 引擎不同甚至没有自己的 Xpath 引擎,这就导致了 XPath 定位速度较慢,而采用 CSS 定位往往能用更简洁的语法快速定位到复杂的元素。因此后文将详细介绍 CSS 定位器的使用方法。

除了以上通用的定位方式之外,在 Selenium IDE 中还可通过 identifier 进行定位,这是最通用也是默认的定位方式,其定位时首先将 identifier 的值视为 ID 继而查找匹配元素,没有匹配项之后再把其看作 name 进行查找,直到找到第一个匹配的元素为止。由于其是默认的定位方式,因此“identifier=”通常也会省略。对于 WebDriver 而言,特有的定位方式更多。首先它可以通过链接文本进行部分匹配,如清单 3 所示;然后它还可以通过标签名或者 CSS 类名的方式进行定位,利用 findElement 的话这两种方式均是定位到第一个匹配条件的元素,利用 findElements 则可获得一个所有满足条件的元素列表,如清单 3 所示。

清单 3. WebDriver 特有的定位方式

//by Partial Link TextWebElement element = driver.findElement(By.partialLinkText("Con")); (10)//in WebDriver//by Tag NameWebElement element = driver.findElement(By.tagName("p")); (09)/in WebDriver//by ClassList<WebElement> WEs = driver.findElements(By.className("required"));(4&5)//in WebDriver

CSS 选择器

CSS 选择器是由关系符分开的一个或多个简单选择器序列组成的选择器序列链,最后一个简单选择器序列的后面还可以添加一个伪元素。简单选择器序列是单纯由简单选择器组成的选择器链,它通常由一个标签选择器或者通配符选择器开头,之后序列中不允许再出现其他标签选择器和通配符选择器。简单选择器可以是 ID 选择器、类选择器、类型(标签)选择器、通配符选择器、属性选择器和伪类选择器。关系符可以是空格、大于号、加号和波浪符。关系符和简单选择器周围允许出现空白(空格符、tab 符、换行符、回车符、换页符)。多个 CSS 选择器还可以用逗号拼接为一个组合选择器,满足任意其中一个选择器的元素都会被该组合选择器选中,逗号的前后允许出现空白。某些选择器支持命名空间前缀,命名空间前缀的声明机制应该由使用选择器的语言指定,如果使用选择器的语言没有指定命名空间前缀声明机制,那么就没有前缀声明。在 CSS 中,命名空间通过 @namespace 规则声明。

清单 4. HTML 示例 2

(01)<html> (02) <body> (03) <form id="loginForm" name="loginFrom"> (04) <input class="required" name="username" type="text" /> (05) <input class="required passfield" name="password" type="password" /> (06) <input name="continue" type="submit" value="Login" /> (07) </form> (08) <p class="ask">Are you sure you want to do this?</p> (09) <a href="continue.html">Continue</a> (10) <a href="cancel.html" hreflang=en-US>Cancel</a> (11) <div> (12) <ul id="structure"> (13) <li>Cat</li> (14) <li>Dog</li> (15) <p>fish</p> (16) <li>Car</li> (17) <li>Goat</li> (18) </ul> (19) </div> (20)</body> (21)<html>简单选择器ID、类、类型(标签)、通配符选择器

文档中可能包含被声明为 ID 类型的属性,ID 类型的属性的特殊之处在于一份文档中的任意两个元素不会有相同的 ID 值。无论文档语言是什么,ID 类型的属性可以用来唯一地标识它所在的元素。ID 选择器由数目符号 (U+0023, #) 和合法的 ID 值组成,ID 选择器指代具有与定位器匹配的 ID 值的文档元素,如清单 5 所示 (行末括号中的数字显示当前行定位器将定位到清单 4HTML 文档中的第几行元素)。当在 HTML 中表示 class 属性时通常将句点符号 ( U+002E) 作为~=的替代符号,因此在 HTML 中 div.value 与 div[class~=value] 具有相同的意义,均定位到 class 为 value 的 div 元素。需要特别注意的是形如 p.pastoral.marine{color:green} 的选择器将匹配到 class 属性既包含 pastoral 又包含 marine 且二者用空格分隔的 p 标签,例如匹配到 class="pastoral blue aqua marine"而匹配不到 class="pastoral blue"。类型选择器中的类型是元素类型的名称,类型选择器指代文档树中具有相同类型的元素,如清单 5 所示。通配符选择器使用星号 (* U+002A) 指代任意元素类型的合法名称。如果星号表示的通配符选择器不是简单选择器序列的唯一组件或者它的后面紧跟着一个伪元素,那么可以省略该星号而暗指含有一个通配符选择器,然而有些情况下不推荐省略,比如 div *:first-child 就比 div :first-child 更易读,不至于和 div:first-child 混淆。另外类型选择器和通配符选择器都支持命名空间前缀,命名空间前缀使用竖线 (U+007C, |) 与选择器分隔,可以为空也可以为通配符星号。在没有命名空间前缀和分隔符的情况下,若没有声明命名空间则表示任意命名空间,若已声明默认命名空间则表示默认命名空间。

属性选择器

属性选择器通过对元素属性进行匹配来进行选择和定位。属性选择器又分为存在和值选择器以及子串匹配属性选择器。前者又分为四种:[att] 指代具有 att 属性的元素,而不论属性的值是什么;[att=val] 指代属性的值为 val 的元素;[att~=val] 指代这样的元素,其属性值由空格分隔的多个值组成,其中一个值和 val 完全匹配;[att|=val] 指代属性值为 val 或者前缀为“val-”。子串匹配属性选择器提供了匹配属性值子串的能力,比如 [att^=val] 指代属性值前缀为 val 的元素;[att$=val] 指代属性值后缀为 val 的元素;[att*=val] 指代属性值中含有 val 字符串的元素。在这两种属性选择器中属性值必须为 CSS 合法字符,大小写敏感度与具体的文档语言有关。详细示例如清单 5 所示。属性选择器也支持命名空间前缀,与类型和通配符选择器不同的是对于没有命名空间前缀或者命名空间前缀为空的属性选择器,其只匹配到没有命名空间前缀的元素。

伪类选择器

伪类选择器可以说是定位 Web 元素的最后救命稻草,它允许使用文档树以外的信息选取元素,这能完成很多其它选择器不能完成的工作。伪类总是由一个前面加了冒号的伪类名组成,伪类可以存在于所有的选择器序列中,它可以位于主选择器或者通配符选择器之后。伪类区分大小写,有些伪类是互斥的,有些伪类则可以同时使用。伪类可以是动态的,某种意义上说随着用户与文档的交互一个伪类可以获得或者失去对一个元素的匹配。伪类从实现方式可分为动态伪类(如互斥的:link 和:visited, :hover, :active, :focus),目的伪类(:target),语言伪类(:lang),元素状态伪类(:enabled, :disabled, :checked, :indeterminate),结构伪类,内含伪类和否定伪类,若以定位元素为目的的话这里只有结构伪类和内含伪类才对我们有用,其他伪类主要应用在元素样式渲染领域特别是随着用户操作自动改变元素样式的场景。

结构伪类可以基于文档树的结构定位元素,其中标准文本和其它非节点元素没有被算进父节点的子节点列表中,子节点的位置索引从 1 开始计算。结构伪类包含十二种::root 伪类指代文档的根节点,在 Html4 中通常指 HTML 元素;:nth-child(an+b), n>=0 伪类指代在第 an+b 个孩子节点,即其之前有 an+b-1 个兄弟节点的元素,举例来说:nth-child(2n) 指代第偶数个孩子节点,:nth-child(2n+1) 指代第奇数个孩子节点,:nth-child(4) 指代第 4 个元素孩子节点;tag:nth-of-type(an+b), n>=0 指代第 an+b 个类型为 tag 的孩子节点,非 tag 类型的节点不参与计数;:nth-last-child(an+b),n>=0 伪类指代从后往前数第 an+b 个孩子节点,即其后有 an+b-1 个兄弟节点;:nth-last-of-type 指代从后往前数第 an+b 个类型为 tag 的节点;:first-child,:last-child,:first-of-type,:last-of-type 分别是上述四种伪类的特例,指代第一个或者最后一个孩子节点;:only-child 伪类指代没有兄弟节点的孩子节点;:only-of-type 伪类指代没有相同类型的兄弟节点的孩子节点;:empty 伪类指代没有孩子节点的节点。详细示例见清单 5。

内含伪类(:contains())通过元素上包含的文本来定位元素,由于在翻译验证性测试的特殊性,该定位方法需配合英文文本与本地化翻译文本的映射才能有效使用。

清单 5. CSS 简单选择器

//by ID selector#loginForm(03)//by Class selector.ask(08)/by Type selectorp.ask(08)//by Universal selector*|*(all)//by attribute presence and value selectorinput[value](06)input[name="continue"](06)input[class~="required"][name="password"](05)a[hreflang|="en"](10)//by substring matching attribute selectora[href^="cancel"](10)a[name$="name"](04)a[name*="pass"](05)//by structural pseudo-classesul#structure li:nth-child(4)//只有当第四个子元素是 li 时才可成功定位到 (16)ul#structure li:nth-of-type(4)(17)ul#structure nth-last-child(3)(15)ul#structure li:nth-last-of-type(3)(14)//by contains pseudo-classli:contains("Cat")(13)关系选择器

由于编码不规范等问题,仅仅通过简单选择器有时候并不能唯一定位到我们预期得到的元素,这时我们还可以通过元素间的代继关系,首先定位到目标元素的祖先或父亲或兄弟节点,然后借助关系选择器进行定位。常见的关系选择器有后代选择器、子选择器和兄弟选择器三种:后代选择器使用空格分隔两个简单选择器以代表二者具有祖先、后代关系,形如“A B”的后代选择器代表目标元素 B 为 A 的任意后代元素;子选择器使用大于号分隔两个简单选择器以代表其父子关系,形如“A B”的子选择器代表目标元素 B 为 A 的子元素;兄弟选择器分为两种,相邻兄弟选择器和一般兄弟选择器。相邻兄弟选择器使用加号分隔两个简单选择器以代表二者具有相同的父元素且位置临近,形如“A + B”的兄弟选择器代表目标元素 B 为紧随 A 后面的兄弟元素。一般兄弟选择器使用波浪号分隔两个简单选择器以代表后者与前者具有相同的父元素,而并不要求这两个元素位置临近。如清单 6 所示:

清单 6. 关系选择器

//by Descendant combinatordiv p(15)//by Child combinatorsbody > p(08)//by General sibling combinatorform + p 或者 div ~ p(08)

技巧&难点拾遗

由上文可见,在编写翻译验证性测试自动化脚本的时候一般这样依次选取定位元素的方法:有 ID 或者唯一 name 属性就直接用其定位。对于无 ID 或唯一 name 的情况,属性组合能唯一定位的可采用 CSS 属性选择器,文档结构能唯一定位的可采用 CSS 结构伪类选择器;对于 CSS 属性选择器和结构伪类仍不能解决的情况,如果相关元素可以精确定位的话还可以借助关系选择器进行定位。最后,虽然翻译验证性测试自动化脚本“一次编写,多个语言环境执行”的特点限制了 CSS 内含伪类的开箱即用,但是如果能借助外部程序实现用户界面中需要翻译的英文字符串与翻译好的本地化字符串之间的映射的话,可以直接在英文环境下编写自动化脚本时将英文字符串作为内含伪类的参数定位元素,当在其他本地化环境下运行脚本时将内含伪类的参数替换为本地化字符串即可。

此外,有时会发现明明定位器语法正确但是仍然无法获得元素,这可能是由于 iframe 存在的缘故。对于 iframe 里的元素,要先显示进入那个 iframe 之后才可定位(比如在 selenium IDE 里要先 selectFrame 进入那个 iframe,参数为 iframe 的名字)。

最后,实际应用中一般无需完全掌握 XPath 或 CSS 选择器的语法,利用一些诸如 XPath Checker和 Firebug/FirePath 的浏览器插件可以方便地获取 XPath/CSS Path 并验证其正确性(一般在插件控制台中可以使用$$() 验证 CSS Path,利用 $x() 验证 XPath)。

总结

综上所述,由于 Web 技术的发展及翻译验证性自动化测试需求的特殊性,在编写 Selenium 自动化脚本定位元素时存在着一些难点,本文通过实例详述了各种定位尤其是 CSS Path 定位的方法,并针对上述难点分享了一些个人见解,希望对大家有所启发。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。