2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 【Go|第6期】浅谈Lorca页面中Chrome正受到自动测试软件的控制

【Go|第6期】浅谈Lorca页面中Chrome正受到自动测试软件的控制

时间:2024-05-10 13:07:21

相关推荐

【Go|第6期】浅谈Lorca页面中Chrome正受到自动测试软件的控制

日期:7月8日

作者:Commas

签名:(ง •_•)ง 积跬步以致千里,积小流以成江海……

注释:如果您觉得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方,还望各位大佬不吝赐教,谢谢^ - ^

1.01365 = 37.7834;0.99365 = 0.0255

1.02365 = 1377.4083;0.98365 = 0.0006

文章目录

一、前言二、分析问题(1)打开 Lorca 库(2)分析 Lorca 库中的 New 函数 三、解决问题四、最终效果展示

一、前言

上期教程《【Go|第5期】Lorca无法正常运行的解决方案》解决了Chrome安全机制导致无法正常运行Lorca程序的问题。小伙伴们可能又发现了另外一个问题,Lorca窗口的副标题上多了一行非常醒目的字:Chrome正受到自动测试软件的控制。虽然功能方面不受影响,但是这一行字却足以让你的用户感到困惑。

示例一:

示例二:

示例三:

二、分析问题

关于“Chrome正受到自动测试软件的控制”这个副标题的问题,一般是由于浏览器的自动化测试工具插件所引起的。这些工具可能会在浏览器窗口的标题栏中显示此消息,以指示当前的浏览器会话处于自动化测试模式下。

第一点,Lorca整个运行过程中,没有使用Selenium或其他类似的自动化测试框架进行Web

应用程序测试;第二点,Lorca在启动的时候,添加了禁用浏览器扩展(Extensions)功能的命令行启动参数;第三点,旧版Chrome不会显示此类副标题,可能没有实现这一功能,而新版则增加了这个浏览器行为,旨在提醒用户当前浏览器正处于自动化测试模式下。

不确定未来最新版本会不会解决此问题,与其寄托未来,不如把握现在。既然是自动化测试(automation这个因素引起的,那么我们是否可以查找一下Lorca是否运行的时候有添加此类参数呢?

(1)打开 Lorca 库

main.go的代码片段:

package mainimport ("log""net/url""/zserge/lorca")func main() {// Create UI with basic HTML passed via data URIui, err := lorca.New("data:text/html,"+url.PathEscape(`<html><head><title>Hello</title></head><body><h1>Hello, world!</h1></body></html>`), "", 480, 320, "--remote-allow-origins=*")if err != nil {log.Fatal(err)}defer ui.Close()// Wait until UI window is closed<-ui.Done()}

截图说明:

Ctrl + 鼠标左键,点选lorca.New中的New, 打开Lorca库。Lorca库的ui.go代码片段

func New(url, dir string, width, height int, customArgs ...string) (UI, error) {if url == "" {url = "data:text/html,<html></html>"}tmpDir := ""if dir == "" {name, err := ioutil.TempDir("", "lorca")if err != nil {return nil, err}dir, tmpDir = name, name}args := append(defaultChromeArgs, fmt.Sprintf("--app=%s", url))args = append(args, fmt.Sprintf("--user-data-dir=%s", dir))args = append(args, fmt.Sprintf("--window-size=%d,%d", width, height))args = append(args, customArgs...)args = append(args, "--remote-debugging-port=0")chrome, err := newChromeWithArgs(ChromeExecutable(), args...)done := make(chan struct{})if err != nil {return nil, err}go func() {chrome.cmd.Wait()close(done)}()return &ui{chrome: chrome, done: done, tmpDir: tmpDir}, nil}

(2)分析 Lorca 库中的 New 函数

1、chrome, err := newChromeWithArgs(ChromeExecutable(), args...)这一行代码是创建一个chrome实例,其中args就是启动程序的命令行参数的切片(slice)。

这些参数也并非我们所要查找的参数,这里可以过了。

2、接着,我们顺藤摸瓜看一下customArgs,如下:

var defaultChromeArgs = []string{"--disable-background-networking","--disable-background-timer-throttling","--disable-backgrounding-occluded-windows","--disable-breakpad","--disable-client-side-phishing-detection","--disable-default-apps","--disable-dev-shm-usage","--disable-infobars","--disable-extensions","--disable-features=site-per-process","--disable-hang-monitor","--disable-ipc-flooding-protection","--disable-popup-blocking","--disable-prompt-on-repost","--disable-renderer-backgrounding","--disable-sync","--disable-translate","--disable-windows10-custom-titlebar","--metrics-recording-only","--no-first-run","--no-default-browser-check","--safebrowsing-disable-auto-update","--enable-automation","--password-store=basic","--use-mock-keychain",}

其中,--enable-automation貌似与自动化测试automation)有关,这不就是我们想要找到参数吗?

另外,在上述命令行中,我们也发现了--disable-infobars命令,用于启动Chromium网页浏览器并禁用副标题(也叫做信息栏)功能。该信息栏就是浏览器窗口顶部显示通知、警告或其他消息的小型信息栏,然而新版chrome目前已不再支持该命令了,这才是导致问题出现的真正原因。

三、解决问题

不希望看到"Chrome正受到自动测试软件的控制" 这个副标题,可以在启动Chrome时省略--enable-automation标志,或者将其设置为--disable-automation。这里我们以省略--enable-automation做演示:

完整的ui.go代码,可以直接拿走,覆盖原来的代码即可使用,如下:

package lorcaimport ("encoding/json""errors""fmt""io/ioutil""os""reflect")// UI interface allows talking to the HTML5 UI from Go.type UI interface {Load(url string) errorBounds() (Bounds, error)SetBounds(Bounds) errorBind(name string, f interface{}) errorEval(js string) ValueDone() <-chan struct{}Close() error}type ui struct {chrome *chromedone chan struct{}tmpDir string}var defaultChromeArgs = []string{"--disable-background-networking","--disable-background-timer-throttling","--disable-backgrounding-occluded-windows","--disable-breakpad","--disable-client-side-phishing-detection","--disable-default-apps","--disable-dev-shm-usage","--disable-infobars","--disable-extensions","--disable-features=site-per-process","--disable-hang-monitor","--disable-ipc-flooding-protection","--disable-popup-blocking","--disable-prompt-on-repost","--disable-renderer-backgrounding","--disable-sync","--disable-translate","--disable-windows10-custom-titlebar","--metrics-recording-only","--no-first-run","--no-default-browser-check","--safebrowsing-disable-auto-update","--password-store=basic","--use-mock-keychain",}// New returns a new HTML5 UI for the given URL, user profile directory, window// size and other options passed to the browser engine. If URL is an empty// string - a blank page is displayed. If user profile directory is an empty// string - a temporary directory is created and it will be removed on// ui.Close(). You might want to use "--headless" custom CLI argument to test// your UI code.func New(url, dir string, width, height int, customArgs ...string) (UI, error) {if url == "" {url = "data:text/html,<html></html>"}tmpDir := ""if dir == "" {name, err := ioutil.TempDir("", "lorca")if err != nil {return nil, err}dir, tmpDir = name, name}args := append(defaultChromeArgs, fmt.Sprintf("--app=%s", url))args = append(args, fmt.Sprintf("--user-data-dir=%s", dir))args = append(args, fmt.Sprintf("--window-size=%d,%d", width, height))args = append(args, customArgs...)args = append(args, "--remote-debugging-port=0")chrome, err := newChromeWithArgs(ChromeExecutable(), args...)done := make(chan struct{})if err != nil {return nil, err}go func() {chrome.cmd.Wait()close(done)}()return &ui{chrome: chrome, done: done, tmpDir: tmpDir}, nil}func (u *ui) Done() <-chan struct{} {return u.done}func (u *ui) Close() error {// ignore err, as the chrome process might be already dead, when user close the window.u.chrome.kill()<-u.doneif u.tmpDir != "" {if err := os.RemoveAll(u.tmpDir); err != nil {return err}}return nil}func (u *ui) Load(url string) error {return u.chrome.load(url) }func (u *ui) Bind(name string, f interface{}) error {v := reflect.ValueOf(f)// f must be a functionif v.Kind() != reflect.Func {return errors.New("only functions can be bound")}// f must return either value and error or just errorif n := v.Type().NumOut(); n > 2 {return errors.New("function may only return a value or a value+error")}return u.chrome.bind(name, func(raw []json.RawMessage) (interface{}, error) {if len(raw) != v.Type().NumIn() {return nil, errors.New("function arguments mismatch")}args := []reflect.Value{}for i := range raw {arg := reflect.New(v.Type().In(i))if err := json.Unmarshal(raw[i], arg.Interface()); err != nil {return nil, err}args = append(args, arg.Elem())}errorType := reflect.TypeOf((*error)(nil)).Elem()res := v.Call(args)switch len(res) {case 0:// No results from the function, just return nilreturn nil, nilcase 1:// One result may be a value, or an errorif res[0].Type().Implements(errorType) {if res[0].Interface() != nil {return nil, res[0].Interface().(error)}return nil, nil}return res[0].Interface(), nilcase 2:// Two results: first one is value, second is errorif !res[1].Type().Implements(errorType) {return nil, errors.New("second return value must be an error")}if res[1].Interface() == nil {return res[0].Interface(), nil}return res[0].Interface(), res[1].Interface().(error)default:return nil, errors.New("unexpected number of return values")}})}func (u *ui) Eval(js string) Value {v, err := u.chrome.eval(js)return value{err: err, raw: v}}func (u *ui) SetBounds(b Bounds) error {return u.chrome.setBounds(b)}func (u *ui) Bounds() (Bounds, error) {return u.chrome.bounds()}

四、最终效果展示

示例一:

示例二:

示例三:

参考文章:

《List of Chromium Command Line Switches》

我的微信公众号会飞的小猴子,等你来关注哦 ^ - ^

版权声明:本文为博主原创文章,如需转载,请给出:

原文链接:/qq_35844043/article/details/131612569

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。