这里有一些在写测试用例时可能用得上的方法和技巧。


### 1、选择节点的方法

开发者可以通过几种不同的方法来指定需要操作的节点。

#### 通过节点的Path值来指定节点

Path的格式为：

```
{节点的className[节点属性=目标值|.......]}>或者.{节点的className[节点属性=目标值|.......]}.....
```

Path中节点由 {} 包围，className作为节点的名称，后方 [] 中包括节点的额外选择条件。额外选择条件可不填写，条件格式为 k=v ，多个条件之间用 | 连接，例如：

```
{a[k1=v1|k2=v2]}
```

表示该Path会选择className=a，同时满足属性k1=v1以及k2=v2的节点。

多个节点之间支持由 . 或者 > 连接，它们分别表示：

   1) . 为选择当前节点的后代节点，即当前节点的所有后代节点都会作为备选。

   2) \> 为仅选择当前节点的子节点。

例如：

```
  {a}.{b}>{c}
```

Path可以调用findPath方法传入调用，获取对应的NodeSelector实例对象。CaseContext实例对象或者NodeSelector实例对象都可以调用findPath方法，返回值为NodeSelector实例对象，如：

```javascript
tmp = await c.findPath("{a}.{b}>{c}") //JavaScript
```

```python
tmp = c.find_path("{a}.{b}>{c}") #Python
```


#### 通过链式调用来指定节点

如果不想使用Path选择节点，还可以使用链式调用的方式：

```javascript
tmp = await c.select((n)=>{ return (n["a"] || "") === "b" }).child({"c" : "d"}) //JavaScript
```

```python
tmp = c.select(lambda n: n.get("a",None) == "b").child({"c" : "d"}) #Python
```

**注意，JavaScript版本中 CaseContext实例对象的findPath方法以及select、child方法都是async function，调用时需要通过await 获取结果**


#### 通过图像识别来指定节点

测试框架提供图像识别的API，可以根据对目标图片的识别结果来获取其位置并进行交互。

   - JavaScript版本调用方式：

```javascript
let imgPath = path.join("img","1.png") //为了兼容跨平台，请使用系统库生成相对路径
tmp = await c.findImg(imgPath)
```

   - Python版本调用方式：

```python
img_path = os.path.join("img","1.png") #为了兼容跨平台，请使用系统库生成相对路径
tmp = c.find_img(img_path)
```

目标图片的路径，是基于测试Case路径的。如果目标图片的绝对路径为 ~/**{workspace}**/img/1.png的话，则findImg传入的imgPath则为img/1.png。

findImg函数返回的是ImgSelector实例对象，可以使用该对象对目标图片位置进行操作。

**Tips** 

- 传入的imgPath由于跨平台原因，最好使用path.join方式进行连接。
- 图片识别的准确性可能会存在一定误差，如有问题请反馈给我们，谢谢。



### 2、操作节点的方法

测试框架目前支持点击、滑动等操作。通过调用ImgSelector实例对象以及NodeSelector实例对象的tap或者swipe方法，触发对应操作。每次操作之后，建议考虑游戏具体场景适当等待。
如果搜索节点时，未找到目标节点，则返回的ImgSelector实例对象或NodeSelector实例对象内容为空，这时触发事件会产生error。建议如果无法确定是否能获取到节点的时候，通过isEmpty()判断是否为空。
如果满足条件的节点有多个，则NodeSelector实例对象也会包括多个节点对象。这时触发事件，则会产生error。如果出现这种问题，建议调整选择条件。  


### 3、完整的Case示例

- JavaScript版本：

```javascript
const mini_game_test = require("mini_game_test")
const BaseCase = mini_game_test.BaseCase
const logger = mini_game_test.logger

class Test extends BaseCase {
    async run(c) {
        logger.info("start")

        let tmp = null
        //获取节点
        tmp = await c.findPath("{laya.display.Stage[nodeType=laya.display.Stage|covered=false]}>{laya.display.Sprite[index=0|nodeType=laya.display.Sprite|covered=false]}>{laya.display.Sprite[index=2|nodeType=laya.display.Sprite]}>{laya.display.Sprite[index=2|nodeType=laya.display.Sprite|covered=false]}")
        //点击
        await tmp.tap()
        //等待
        await c.sleep(3000)
        let endStatus = false
        for (let i = 0; i {laya.display.Sprite[index=0|nodeType=laya.display.Sprite|covered=false]}>{laya.display.Sprite[index=5|nodeType=laya.display.Sprite|covered=false]}>{laya.display.Sprite[index=3|nodeType=laya.display.Sprite|covered=false]}")
            if (!tmp.isEmpty()) {
                logger.info("game end")
                endStatus = true
                break
            }
        }

        if (!endStatus) {
            logger.info("game not end or game error")
            return
        }

        tmp = await c.findPath("{laya.display.Stage[nodeType=laya.display.Stage|covered=false]}>{laya.display.Sprite[index=0|nodeType=laya.display.Sprite|covered=false]}>{laya.display.Sprite[index=5|nodeType=laya.display.Sprite|covered=false]}>{laya.display.Sprite[index=3|nodeType=laya.display.Sprite|covered=false]}")
        await tmp.tap()
        await c.sleep(3000)
        tmp = await c.findPath("{laya.display.Stage[nodeType=laya.display.Stage|covered=false]}>{laya.display.Sprite[index=0|nodeType=laya.display.Sprite|covered=false]}>{laya.display.Sprite[index=6|nodeType=laya.display.Sprite|covered=false]}>{laya.display.Sprite[index=0|nodeType=laya.display.Sprite|covered=false]}")
        await tmp.tap()
        await c.sleep(3000)
        tmp = await c.findPath("{laya.display.Stage[nodeType=laya.display.Stage|covered=false]}>{laya.display.Sprite[index=0|nodeType=laya.display.Sprite|covered=false]}>{laya.display.Sprite[index=5|nodeType=laya.display.Sprite|covered=false]}>{laya.display.Sprite[index=4|nodeType=laya.display.Sprite|covered=false]}")
        await tmp.tap()
        await c.sleep(3000)
        tmp = await c.findPath("{laya.display.Stage[nodeType=laya.display.Stage|covered=false]}>{laya.display.Sprite[index=0|nodeType=laya.display.Sprite|covered=false]}>{laya.display.Sprite[nodeType=laya.display.Sprite|covered=false]}>{laya.display.Sprite[index=7|nodeType=laya.display.Sprite|covered=false]}")
        await tmp.tap()
        await c.sleep(3000)
    }
}

logger.debug("start")

const t = new Test()
t.start()
```

- Python版本：

```python
# -*- coding: utf-8 -*-
from mini_game_test_case_py.case.BaseCase import BaseCase
from mini_game_test_case_py.lib import config
from mini_game_test_case_py.lib import Asserts
from mini_game_test_case_py.lib import Logger
import time

class TestCase(BaseCase):
    def run(self, c):
        Logger.info("start case")
        #获取开始按钮
        start_node = c.find_path(
            "{laya.display.Stage[covered=false]}>{laya.display.Sprite[index=0|covered=false]}>{laya.display.Sprite}>{laya.display.Sprite[index=2|covered=false]}")
        #判断开始按钮是否存在
        Asserts.assert_nodeselector_exists(start_node)
        #点击
        start_node.tap()
        c.sleep(6000)

        start_time = time.time()

        endStatus = False

        #循环判断paihang_node是否出现
        while time.time() - start_time {laya.display.Sprite[index=0|covered=false]}>{laya.display.Sprite[index=5|covered=false]}>{laya.display.Sprite[index=3|covered=false]}")
            if not paihang_node.is_empty():
                Logger.info("game end")
                endStatus = True
                break

        if not endStatus:
            Logger.info("game end error")
            return

        tmp = c.find_path("{laya.display.Stage[covered=false]}>{laya.display.Sprite[index=0|covered=false]}>{laya.display.Sprite[index=5|covered=false]}>{laya.display.Sprite[index=3|covered=false]}")
        Asserts.assert_nodeselector_exists(tmp)
        tmp.tap()
        c.sleep(6000)
        tmp = c.find_path("{laya.display.Stage[covered=false]}>{laya.display.Sprite[index=0|covered=false]}>{laya.display.Sprite[index=6|covered=false]}>{laya.display.Sprite[index=0|covered=false]}")
        Asserts.assert_nodeselector_exists(tmp)
        tmp.tap()
        c.sleep(6000)
        tmp = c.find_path("{laya.display.Stage[covered=false]}>{laya.display.Sprite[index=0|covered=false]}>{laya.display.Sprite[index=5|covered=false]}>{laya.display.Sprite[index=4|covered=false]}")
        Asserts.assert_nodeselector_exists(tmp)
        tmp.tap()
        c.sleep(6000)
        tmp = c.find_path("{laya.display.Stage[covered=false]}>{laya.display.Sprite[index=0|covered=false]}>{laya.display.Sprite[covered=false]}>{laya.display.Sprite[index=7|covered=false]}")
        Asserts.assert_nodeselector_exists(tmp)
        tmp.tap()
        c.sleep(6000)        
        Logger.info("end test")

t = TestCase()
t.start()
```
