STF stf 结合 webstorm 配置断点调试环境

陈恒捷 · 2016年11月17日 · 最后由 sxb0822 回复于 2020年03月31日 · 115 次阅读
本帖已被设为精华帖!

最近在搞 stf 的二次开发,看了网上许多文章,大多是对 stf 架构及改造方案方面的分享,但没找到关于 stf 断点调试的相关文章,所以在这里分享下自己探索到的方法。

什么是断点调试

断点调试,顾名思义,就是能够在程序运行过程中添加断点协助调试。结合 IDE(我用的是 WebStorm),能够十分方便地在运行过程中获取程序在断点停留时的各种信息,包括但不限于变量值、内存帧情况。同时也可以在断点处执行一些表达式,确定表达式的执行结果。

这是一张断点调试的图(来自 http://www.cnblogs.com/jinguangguo/p/4809886.html),可以看到处于断点时能获取到各种信息:

可以执行你想要执行的表达式:

可以看出,断点调试对于开发效率的提升是十分明显的。

stf 后端调试配置探究

大家都知道使用 stf local 可以启动 stf ,然而直接把它如下图那样配置到 webstorm 中:

直接 Run 不会出任何问题,然而进行 debug 的时候,就会有如下报错了:

经过多番查找,最终找到了的原因为:

stf local 命令中实际上是通过 child-process 的 fork 方法按照固定组合启动各个 stf 组件。默认情况下,child-process 创建的程序中使用的调试参数会和当前程序一致,因此会由于 debug 端口重复使用而报出上面的错误

经过查找,有一个专门解决这个问题的组件,叫 child-process-debug 。通过把 child-process 改为用这个组件后(修改 lib/util/procutil.js 这个文件就好,因为 local 的 fork 都是用这个文件里面的 fork 方法的。),调试参数一致的问题解决了,但还是有报错:

然后这段时间刚好也开始尝试使用 docker 一个一个组件地部署 stf ,灵机一动,也许调试的时候也可以这样做?

stf 后端调试配置

原理很简单,就是把原来 stf local 启动的各个进程改为一个一个配置来启动,配置的内容和 local 保持一致就好。

stf local 中的启动配置:

INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js triproxy app001 --bind-pub tcp://127.0.0.1:7111 --bind-dealer tcp://127.0.0.1:7112 --bind-pull tcp://127.0.0.1:7113"
INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js triproxy dev001 --bind-pub tcp://127.0.0.1:7114 --bind-dealer tcp://127.0.0.1:7115 --bind-pull tcp://127.0.0.1:7116"
INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js processor proc001 --connect-app-dealer tcp://127.0.0.1:7112 --connect-dev-dealer tcp://127.0.0.1:7115"
INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js processor proc002 --connect-app-dealer tcp://127.0.0.1:7112 --connect-dev-dealer tcp://127.0.0.1:7115"
INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js reaper reaper001 --connect-push tcp://127.0.0.1:7116 --connect-sub tcp://127.0.0.1:7111"
INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js provider --name chenhengjiedeMac-mini.local --min-port 7400 --max-port 7700 --connect-sub tcp://127.0.0.1:7114 --connect-push tcp://127.0.0.1:7116 --group-timeout 900 --public-ip localhost --storage-url http://localhost:7100/ --adb-host 127.0.0.1 --adb-port 5037 --vnc-initial-size 600x800"
INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js auth-mock --port 7120 --secret kute kittykat --app-url http://localhost:7100/"
INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js app --port 7105 --secret kute kittykat --auth-url http://localhost:7100/auth/mock/ --websocket-url http://localhost:7110/"
INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js api --port 7106 --secret kute kittykat --connect-push tcp://127.0.0.1:7113 --connect-sub tcp://127.0.0.1:7111"
INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js websocket --port 7110 --secret kute kittykat --storage-url http://localhost:7100/ --connect-sub tcp://127.0.0.1:7111 --connect-push tcp://127.0.0.1:7113"
INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js storage-temp --port 7102"
INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js storage-plugin-image --port 7103 --storage-url http://localhost:7100/"
INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js storage-plugin-apk --port 7104 --storage-url http://localhost:7100/"
INF/util:procutil 45859 [*] Forking "/Users/chenhengjie/Projects/ppmoney/tools/stf/lib/cli.js poorxy --port 7100 --app-url http://localhost:7105/ --auth-url http://localhost:7120/ --api-url http://localhost:7106/ --websocket-url http://localhost:7110/ --storage-url http://localhost:7102/ --storage-plugin-image-url http://localhost:7103/ --storage-plugin-apk-url http://localhost:7104/"

migrate 的一般情况下不需要 debug ,需要的时候直接 stf migrate 就好了,所以这里就不另外放上来了。

放一张 storage-tmp 的对应 webstorm 截图,大家可以参考下:

其中有一点要特别注意,由于 provider 每增加一台设备会增加一个子进程,所以 provider 一般情况下最好不要用 debug 模式打开,用 run 模式就好。

配置完后,就可以愉快地做断点调试啦~

stf 前端调试配置探究

大家都知道,通过 gulp build 命令可以把前端代码合并更新,然后网页刷新下就是新代码了。

而实际上 stf 前端用的是 webpack 进行的前端各个资源文件的合并,gulp build 的本质是调用了 gulp buildgulp webpack:build 两个子任务。也就是说,实际上代码的合并更新是通过 gulp webpack:build 完成的。

简单看了下 webpack:build 任务的源码,基本就是使用 webpack 本身提供的函数进行构建。

PS:想对 webpack 有个大致了解,强烈推荐花个 10 分钟左右把 官方 tutorials 过一下。

好了,webpack 作为一个已经比较成熟的框架,webstorm 肯定是提供了调试的支持的。果然,在官方找到了一个调试配置的文章: https://blog.jetbrains.com/webstorm/2015/09/debugging-webpack-applications-in-webstorm/

文章里面的点总结起来就是三个:

  1. webpack 配置里面设置 devtool: "source-map"
  2. 把 webpack 输出的文件夹 build exclude 掉
  3. 做一个 Mapping,把浏览器中的文件和代码中的文件映射起来

实际配置的时候,有一个坑,我发现无论怎么改 webpack.config.js 这个文件里面的 devtool ,scripts 标签页总是无法出现 webpack:// 这样的内容。结果像上面那样探究了一下 webpack:build 任务的源码,它竟然覆盖了 devtool 的配置。。。

// For production
gulp.task('webpack:build', function(callback) {
...

  // 覆盖了 devtool 的配置。。。
  myConfig.devtool = false

 ...
})

那么解决方法也很简单,新建一个 webpack:debug 的任务,内容直接拷贝 webpack:build 的,其中 devtool 改为 'source-map' 就好了。

stf 前端调试配置

好了,总结一下具体的配置方法吧:

  • 在项目根目录的 gulpfilel.js 中添加 webpack:debug 任务
gulp.task('webpack:debug', function(callback) {
  var myConfig = Object.create(webpackStatusConfig)
  myConfig.plugins = myConfig.plugins.concat(
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('production')
      }
    })
  )
  // set devtool to source-map for debug
  myConfig.devtool = 'source-map'

  webpack(myConfig, function(err, stats) {
    if (err) {
      throw new gutil.PluginError('webpack:others', err)
    }

    gutil.log('[webpack:debug]', stats.toString({
      colors: true
    }))
    callback()
  })
})
  • 在之前建立的后端调试配置中,选择 app 的配置,在 Browser/Live Edit 中进行如下配置:

配置就只有这么多了。下面介绍一下用法:

  1. 假设现在你的代码已经改好了,运行下 gulp webpack:debug 任务,生成最新的代码。
  2. 如果目前已经有 javascript 类型的调试器正在运行,停掉它。
  3. 重启下 app 的调试进程
  4. 自动启动的浏览器窗口如果过了 10 秒页面还是空白,直接刷新下,多刷新几次就好了。

总的来说,配置比较简单,但用法略复杂,每次改完代码都得做不少操作才能对新代码进行调试。

总结

stf 相对以前用过的 nodejs 程序(如 appium),相对复杂,调试方式并没有平时普通网站那样把 run 改为 debug 就可以,需要额外进行不少配置。但一旦配置好,开发效率将会有比较明显的提升,至少再也不用加很多 console.log 然后后面又得逐一去掉了。

我提供的方法目前都只能说能用,但说实话,并十分好用,特别是前端,每一次都要跑任务、重启调试器、重新进入当前页,真心累。

如果大家有更好的调试方法,非常欢迎大家在回帖中提出来,我确认后会更新到正文中,以帮助后来人更方便的进行 stf 的调试配置

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 25 条回复 时间 点赞
思寒_seveniruby 将本帖设为了精华贴 11月17日 04:23

加精理由:提供了 stf 调试的新方法尝试 对以后的改造有效率提升

我已经彻底把前端给抛弃了😼

我暂时也放弃了。。。

#4 楼 @lose 我把后端接口化,直接让 web 开发重写了个前端界面。

#5 楼 @0x88 stf 官方的前端是一个很先进的框架,为什么要重写呢

表示已经用 vue 重写完了

#6 楼 @blueshark 我也不想重新呀,但是好多 CSS 样式用不了。如果只提供 HTTP 接口,然后前端就可以不限制于用 angular,随便找个 web 开发做界面,一两周就能搞完。

#8 楼 @0x88 能详细说一下官方原生的前端有什么重大缺点吗?我感觉还不错啊,angularjs 是个很不错的框架,加上 angular-ui,个人感觉还很顺手

#9 楼 @blueshark 其实原生的前端没什么问题,问题在于我们这边没有学 angularjs 的人,而且 angularjs 存在不确定性,比如 angularjs 已经升级到 2.0 版本,而且 2.0 版本不兼容 1.X 版本。所以决定不用原生的 angularjs。

最近一直在思考 STF 使用的场景,目前还不晓得要怎么用才能把 STF 的功能发挥最大化。

#7 楼 @codeskyblue 厉害呀!前端我还是新手,各种学习中,还没达到能重写的水平。

#11 楼 @cqtest 我们是做兼容性测试平台。个人觉得当你需要做的平台和手机管理相关时,stf 用处比较大 。

#12 楼 @chenhengjie123 没有这么复杂的,参考这 stf 很快就写出来了

如何通过一个脚本来启动整个服务?

Bob 回复

你说的是 stf 的服务?stf local 满足不了需要么?

陈恒捷 回复

stf local 是以正常模式启动服务。在 Debug 模式下如何一个脚本来启动呢?现在按照楼主配置,服务需要手动单独开启。[14 个有点多..]

Bob 回复

这个也是我最终没有解决的问题。。。我实际使用就是开了 debug 模式下的服务后长期不关,这样就不用每次都要开服务了。

PS:有些服务不用做 debug 的,用普通模式启动更好,速度也更快。

陈恒捷 回复

屡试不爽。就是 Mac 卡成狗了。。

匿名 #19 · 2018年01月18日
0x88 回复

hi 你好大神 最近在看 stf 的后端代码,不过有很多不了解的地方,后端全部接口化有没有什么经验可以分享

我不是什么大神哈。对于后端接口化我用的是前后端分离,在入口文件 poorxy.js 中加入跨域访问的方法。如下 :

然后把 mock.js 的登录改成 sso 登录(根据你们实际的登录需求),绕过认证,然后就可以通过域名和接口名 get/post。但具体的做法还是得自己花时间去做。

匿名 #21 · 2018年01月19日

学习了 刚接触源码还不熟 我慢慢理解理解

匿名 在 openstf 的手机占用流程 中提及了此贴 02月25日 12:37

@chenhengjie123 ,通过把 child-process 改为 child-process-debug 的代码能贴一下么(修改 lib/util/procutil.js)

来回报社区啦~
stf 断点总是报端口占用中的问题,顺着 “child_process 调试端口占用” 找到了解决方法。使用 node-inspect 带参数的方式,启动每一个子进程。(本人 node 的版本 8.12.0,关于 node debug 这一块,之前的废弃了,有兴趣可以自己了解一下)。
stf 启动起来总共 15 个进程,我当然不是每个子进程都带一个参数启动啦,太麻烦,用程序的思维,改动 util/procutils.js 文件,添加 3 行代码:变量 i 定义,i 传入启动参数,i 自增。完美解决调试问题。

希望对有需要的人有帮助。

codeskyblue 回复

用 vue 重写完了吗?

codeskyblue 回复

好的,谢谢。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册