我已经构建了一个基于Polymer的应用程序。我想为它编写一些端到端测试(不是单元测试,而是用户行为集成测试)。我目前如何做到这一点(2015年5月)?
答案 0 :(得分:4)
过去几天我一直在研究这个问题。尽管在网络上专门讨论一个或另一个相关主题的页面很多,但没有任何文档可以解决这个问题。我能够拼凑出有效的东西。所以这就是。希望这对那些希望为Polymer应用程序编写端到端测试的人有用。我相信,随着Polymer,Web组件和Shadow DOM技术的成熟,将会出现更好的解决方案。
一些细节:Linux,希望在脚本中自动化测试(理想情况是无头),app由许多Polymer元素组成,并由Django服务器提供服务并加载数据。
使用PhantomJS失败
首先,我尝试使用casperjs和phantomjs。 phantomjs是无头的,casperjs有非常好的导航支持,所以我认为这将是一个很好的组合最终。不幸的是,phantomjs不支持HTML5导入,而webcomponents.js polyfill似乎不适用于phantomjs。
使用Selenium
我使用selenium python客户端最终得到了基于Selenium / ChromeDriver的解决方案。我没有用Firefox驱动程序测试这个,所以我不知道这是否有效。以下是您需要做的事情:
为了简化操作,请创建一个目录以将内容放入:
mkdir selenium
安装Google Chrome。我是通过谷歌网站做到这一点并下载了linux版本。然后,将selenium server 2.45和chromedriver 2.15下载到selenium目录中。 E.g。
$ ls selenium/
chromedriver selenium-server-standalone-2.45.0.jar
然后,安装Python Selenium API
$ pip install selenium
运行一个简单的测试:
$ cd selenium
$ cat > test.py
from selenium import webdriver
driver = webdriver.Chrome('./chromedriver')
driver.get("http://localhost:8000/myapp/")
driver.implicitly_wait(3)
print driver.title
content = driver.find_element_by_css_selector('myelement::shadow h3')
print content.text
driver.close()
$ xvfb-run python test.py
(xvfb是运行test.py无头的必要条件)
test.py在名为myelement的自定义Polymer元素中打印出h3元素的内容。例如。如果DOM看起来像
<myelement>
<h3>Hello World</h3>
</myelement>
然后test.py打印&#34; Hello World&#34;。
h3元素出现在myelement的shadow DOM中。 Chrome开发工具会将此h3的CSS选择器列为&#34; myelement#shadow-root h3&#34;。使用Selenium,你可以使用&#34; myelement :: shadow h3&#34;来访问这个h3。作为CSS选择器。
测试和测试数据
我将我的测试组织为Python unittest测试用例,并编写了测试驱动程序脚本。驱动程序脚本分叉,在子进程中创建一个Django dev服务器,并运行&#34; python -m unittest&#34;在父进程中。每个测试用例都使用Python selenium API连接到Django dev服务器。在每个测试用例的setUp和tearDown方法中,我使用我的Django模型类将测试数据注入数据库。
我在xvfb下运行驱动程序脚本 - &#34; xvfb-run python driver.py&#34; - 让它无头。
处理Ajax和双向绑定
我的Polymer应用程序使用ajax加载数据和双向绑定来呈现HTML模板。 Polymer还会呈现模板并异步更新DOM。在我的测试用例中,我依靠Selenium的条件等待来检测数据加载何时完成以及DOM重新呈现。因为某些原因,隐瞒等待(这不是一个好主意)对我不起作用;隐式等待只是立即返回。我还更新了我的HTML模板,以便更加可测试 - 添加DOM ID和独特的文本或CSS选择器,以区分应用程序的不同阶段。
<强>注意事项强>
只使用Selenium作为内部HTML的按钮变得无法点击。如果您有这样的按钮,请使用ActionChains单击它:
chain = ActionChains()
chain.move_to_element(element)
chain.click()
chain.perform()