web页面E2E测试好帮手——Rod简介(三)

发表于:2022-11-03 09:44

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:ag9920    来源:掘金

  获取图片
  思路一样,区别是我们需要获取二进制的图片数据了,这里需要用到 Element 的MustResource方法:
// MustResource is similar to Element.Resource
func (el *Element) MustResource() []byte {
bin, err := el.Resource()
el.e(err)
return bin
}

// Resource returns the "src" content of current element. Such as the jpg of <img src="a.jpg">
func (el *Element) Resource() ([]byte, error) {
src, err := el.Evaluate(evalHelper(js.Resource).ByPromise())
if err != nil {
return nil, err
}

return el.page.GetResource(src.Value.String())
}
  这里会返回一个字节数组,需要我们进行转换。rod 的 util 包也提供了相关方法:
// OutputFile auto creates file if not exists, it will try to detect the data type and
// auto output binary, string or json
func OutputFile(p string, data interface{}) error {
dir := filepath.Dir(p)
_ = Mkdir(dir)

var bin []byte

switch t := data.(type) {
case []byte:
bin = t
case string:
bin = []byte(t)
case io.Reader:
f, _ := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0664)
_, err := io.Copy(f, t)
return err
default:
bin = MustToJSONBytes(data)
}

return ioutil.WriteFile(p, bin, 0664)
}
  这里接收的 data 就可以是个字节数组,p 是文件输出路径。OutputFile 会自行处理创建目录,文件,写入数据的流程。下面我们改下代码看看:
package main

import (
    "github.com/go-rod/rod"
    "github.com/go-rod/rod/lib/utils"
)

func main() {
    page := rod.New().MustConnect().MustPage("https://www.wikipedia.org/")

    page.MustElement("#searchInput").MustInput("earth")
    page.MustElement("#search-form > fieldset > button").MustClick()

    el := page.MustElement("#mw-content-text > div.mw-parser-output > table.infobox > tbody > tr:nth-child(1) > td > a > img")
    _ = utils.OutputFile("b.png", el.MustResource())
}
  重新运行后,我们的 b.png 文件就包含了要爬的图片:
  E2E 示例
  这一节我们来看看官方给出的 E2E 示例。真实的业务场景远比这个复杂,但本质内核都是一样的,大家可以结合相关 API 设计自己的 E2E 流程。
  https://ahfarmer.github.io/calculator/是一个经典的在线计算器,大家可以自己打开看一看,页面非常简单,模拟大家手机的计算器 app。
  假定我们是这个计算器的开发者,希望做端到端测试,就可以借助 rod 的能力,直接在网页上操作加减法,看看最终结果是否符合预期。
  为此,我们还需要借助一些测试框架的断言能力,比较结果。这里官方是用了作者自己的测试库:"github.com/ysmood/got",大家有需求的话其实可以替换成自己常用的。
  第一步,我们需要先创建出一个 Browser 对象,毕竟 E2E 不可能只测几个单独的case,也需要支持并发。这里可以使用一个共用的 Browser 对象。新建一个 setup_test.go,填充以下内容:
// This is the setup file for this test suite.

package main

import (
"testing"

"github.com/go-rod/rod"
"github.com/ysmood/got"
)

// test context
type G struct {
got.G

browser *rod.Browser
}

// setup for tests
var setup = func() func(t *testing.T) G {
browser := rod.New().MustConnect()

return func(t *testing.T) G {
t.Parallel() // run each test concurrently

return G{got.New(t), browser}
}
}()

// a helper function to create an incognito page
func (g G) page(url string) *rod.Page {
page := g.browser.MustIncognito().MustPage(url)
g.Cleanup(page.MustClose)
return page
}
  这里的 page 也是默认开启无痕模式,打开指定的 url,利用了 ysmood/got 的 Cleanup 能力随后进行清理,本质是个 helper 函数。
  第二步,开始校验业务逻辑,新建 calculator_test.go,填充以下内容:
// Package main ...
package main

import "testing"

// test case: 1 + 2 = 3
func TestAdd(t *testing.T) {
g := setup(t)

p := g.page("https://ahfarmer.github.io/calculator")

p.MustElementR("button", "1").MustClick()
p.MustElementR("button", `^\+$`).MustClick()
p.MustElementR("button", "2").MustClick()
p.MustElementR("button", "=").MustClick()

// assert the result with t.Eq
g.Eq(p.MustElement(".component-display").MustText(), "3")
}

// test case: 2 * 3 = 6
func TestMultiple(t *testing.T) {
g := setup(t)

p := g.page("https://ahfarmer.github.io/calculator")

// use for-loop to click each button
for _, regex := range []string{"2", "x", "3", "="} {
p.MustElementR("button", regex).MustClick()
}

g.Eq(p.MustElement(".component-display").MustText(), "6")
}
  这里只是示例,case 比较简单。大家可以自行调整一下试试。
  第一个case我们需要校验加法是否正常我们打开计算器网页,通过 MustElementR 获取到指定元素,触发点击。
// MustElementR is similar to Page.ElementR
func (p *Page) MustElementR(selector, jsRegex string) *Element {
el, err := p.ElementR(selector, jsRegex)
p.e(err)
return el
}

// ElementR retries until an element in the page that matches the css selector and it's text matches the jsRegex,
// then returns the matched element.
func (p *Page) ElementR(selector, jsRegex string) (*Element, error) {
return p.ElementByJS(evalHelper(js.ElementR, selector, jsRegex))
}
  这里的 MustElementR 补充了正则能力,毕竟有些元素单独靠 selector 无法定位,这里是增强的能力。
  触发元素点击后,通过断言,判断文本和指定的结果是否匹配即可。
  第二个 case 也是类似的场景,大家可以由此体会一下 MustElementR 的用法。
  执行测试case和平常的 Golang 单测没有区别,直接 go test 命令即可。
  小结
  这里我们只是拿出来 rod 常见的一些用法,它可以打印,可以转图片,截屏,导出 pdf。可以模拟人为的浏览器操作,整体功能还是非常强大的,建议大家自己动手试一下。官方的 guide 也是很不错的参考资料。
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号