# 自动化测试元素定位最佳实践




最近在翻阅cypress文档的时候发现一些关于自动化测试中元素定位的思考，觉得很有意思，这里跟大家分享一下。


### 核心概念

其实元素定义的核心概念很简单，一些元素总有自己独一无二的一些特点，比如我们每个人都有身份证号，利用这种独特性对元素进行定位，从而进一步做后续操作。

有道是君子有所为有所不为，一些在实践中被证明了是不合适的做法是最好不要去采用的，比如**不要使用有可能发生改变的属性对元素进行定位**。

如果你有能力修改前端代码，那么最佳实践就是:**加一个定位专用的属性，比如```data-*```**，这个属性跟js逻辑以及css样式都无关，这样就做到了定位属性与易变属性(dom/css selector/js selector)隔离。

下面的一些做法是cypress不太推荐的，不过见仁见智，不推荐不代表完全不能这样做。

* 不要用css属性定位，比如```id,class,tag```
* 不要用可能会发生变化的文本文字进行定位，比如按钮上的文字等

### 没有对比就没有伤害

cypress的最佳实践里给大家列举了一些例子进行对比，我们感受一下

| 选择器      | 推荐程度 | 备注 |
| ----------- | ----------- | ---|
| ```cy.get('button').click()```      | 永远不要这样做  | 最差的选择，没有任何上下文，太通用|
| ```cy.get('.btn.btn-large').click()```   | 永远不要这样做  | 很差，这些class很容易发生修改|
| ```cy.get('#main').click()```   | 不太好  | 还行，不过还是跟js和css选择器耦合在一起|
| ```cy.get('[name=submission]').click()	```   | 不太好  | 跟html的name属性耦合在了一起|
| ```cy.contains('Submit').click()```   | 见仁见智  | 好多了，但是仍然跟按钮文本耦合在了一起|
| ```cy.get('[data-cy=submit]').click()```   | 最佳选择  | 单独的属性，与css和js隔离|

### 然而，人生十不如意有八九

上面的一些观点，原则上我是非常赞同的。

但是呢，现实往往比理论更加立体，cypress的理念是对于被测项目的前端代码，你必须百分百有控制权，也就是说你需要是这个项目的前端开发人员。

cypress就是为前端开发人员设计的，这样的要求自然是合情合理的。

但很多情况是我们其实并没办法修改前端代码的，在这种艰苦的条件下，一些妥协是可以有的，比如

* 可以用html的name属性定位，因为这个属性相对稳定
* 可以用dom的id属性定位，因为改id的概率可能会比较低
* 不要用基于dom层级关系的xpath或css定位，这里一般指的是在浏览器上直接拷贝出来的xpath和css选择器

总之最佳实践是有前提的，不需要一味的去迷信最佳实践,在我们的工作场景中找到最适合自己的最佳实践才是王道。




原始封面

![课程图片](https://images.unsplash.com/photo-1473800447596-01729482b8eb?w=300)


