debug的方式有很多最简单的方式是打印log,看log,这个的缺点是比较慢,尤其是用加log的方式来缩小怀疑的范围。因为这是一个不断迭代的过程,最主要的原因,一开始不知道代码哪个地方有问题。只能在所有可能有问题的地方加打印log。然后逐步的缩小怀疑范围。下边介绍一种快速的debug方法。
一半正儿八经的公司,一定会设计UT,UT是对单个功能测试的一种手段,相对于C++来说,测试单位是C++类的所有public方法,private方法通过public方法测试。
UT的价值是可以发现之前肉眼没有发现的错误。这也是TDD(测试开发驱动)这么火的一个原因。
现在C++的UT大多都是GTest, Unitest已经很少有人用。GTest现在可以编译出UT单独的binary,直接使用gdb调试即可。
gdb binary # no args
gdb --args binary arg1 arg2 # has args.
在gdb内部使用gdb的命令即可。
包括如下常用命令。
# 下一步,不进入函数体
n/next
# 下一步,如果是子函数,那么进入子函数
s/step
# 继续运行代码,直到代码结束,或者遇到断点
c/continue
# 打断点 在main函数的90行打断点
b main.cpp:90
# 查看当前上下文的变量值
info locals
# 查看当前函数传入的形参值
info args
NOTE
MT测试的level比UT高,关注点不再是单个的类,而是在类之间的交互上,SCT的测试level比MT高,在整个binary上。
基本上相当于模拟整个binary的运行环境,进行测试。
业界公共一般使用pytest框架,这是一个python语言的框架,用这个框架将测试对象,也就是我们自己的binary 运行起来,然后等待外界输入,也就是需要的测试交互。
用C++代码写成的binary,会在pytest内部启动。一般使用subprocess模块启动:如下命令启动
self.__proc = subprocess.Popen(self.start_command, shell=True)
start_command:指的是运行自己binary的命令。例如下:
helloWorld arg
当然不仅仅是起来binary,你所有需要启动这个binary的工作都要在pytest里面搞定,具体如何使用就需要参照pytest自己的doc.
参照pytest的doc写case。
首先给pytest的case打断点, 有两种方式
import pdb
pdb.set_trace()
pytest --trace test_hello.py
由于我们自己的binary已经在pytest上启动,也就是说不需要从gdb再次启动,可以使用gdb attach的方式来attach到这个进程
实现的脚本如下:
gdbhelloworld.py
import os
import subprocess
pid = subprocess.check_output("pgrep helloworld", shell=True).strip()
print(pid)
gdb.execute('file ' + 'path of binary')
gdb.execute('attach ' + pid.decode('ascii'))
解释:
gdbhelloworld
#!/bin/bash
cgdb -x path of gdbhelloworld.py
解释:
为了方便使用,加入一个脚本,使用cgdb,方便看到调试代码上下文。cgdb可以认为是对gdb的一个封装。可以一边调试,一边方便的看到当前正在运行的代码上下文
执行顺序
b main.cpp:10
None