ylib测试用例指引

写1小时测试用例,省10小时debug

路径

  • 在package中的testcase中出现的所有路径参数都是相对路径.确保我可以跑通测试用例
  • 为了避免各种import的路径问题.负责人在pyCharm中打开ylib目录,然后运行里面的测试用例,测试用例通过了可以通知我.
  • 针对特殊值的测试(称为鲁棒性检测).例如下面的代码。 这类测试可以命名为test_robust_<名词>.
[],{}, pd.DataFrame(), None
  • 测试用例要考虑处理网路请求无返回等情况.可以通过自己定义模拟函数的方式来实现
# 需要现在原先的代码中把对于网络请求的依赖使用RequestBhv实例隔离出来.
class RequestBhv
    def mockrequest(method,url):
        raise TimeOutError # 外部调用的时候会直接报这个错误
  • 需要函数有正确报错的行为.可以参考下面的代码
def test_convert_rel_path():
    is_error = False
    try:
        convert_rel_path(rel_to="yeascript")
    except:
        is_error = True
    assert is_error

自动执行

  • 测试用例都要有assert 语句来检查结果是否符合预期.未来可以全自动跑测试用例.参考下面的重构:
ftp_behavior = FtpBhv()
ftp_behavior.io_login()
print(ftp_behavior.is_dir_exist(r'\test\sidyph'))
ftp_behavior = FtpBhv()
ftp_behavior.io_login()
the_path = r'\test\sidyph'
try:
    ftp_behavior.remove(the_path)
except e:
    pass
assert ftp_behavior.is_dir_exist(the_path) == False # 这个assert替代了之前使用人肉看print结果
  • assert 要判断具体的值,而不是仅仅检查类型.参考下面的代码:
def test_get_py_code_frm(self):
        py_coding_frm = self.get_code_report.get_py_code_frm(self.py_file_path)
        assert isinstance(py_coding_frm, pd.DataFrame) # 仅仅判断类型是不够的
        assert py_coding_frm['num'].tolist() == [999,123] # 需要判断具体值
        assert py_coding_frm['author'].tolist() == ['cc','cc'] # 需要判断具体值

可以使用print(DataFrame.tolist())把list形式的数据打印出来,然后复制粘贴到代码中.参考下图:

image.png

测试覆盖率

  • 一般每个类都有对应的一个测试用例.里面可以有多个assert.这个类的所有的外方的方法都会被执行到。所有的中间过程都要assert.例如下面的代码:
input = 1
step1 = Step1()
res1 = step1.do1(input)
assert res1 == 2 # 所有的中间过程都要assert.
res2 = step1.do2(res1)
assert res2 == 2
  • 如果某个方法存在3层(for-if-else), 必须检查里面的所有if-else是否正确.
  • 步骤类至少对应一个测试用例.
  • 每个测试用例都要有注释,写出这个测试用例检查的问题是什么.
def test_iostate_read():
"""测试iostate.read方法,在文件不存在的时候可以正常报错"""

建议写2个测试用例之后再实际开发

测试用例的模板如下.大家可以利用模板加速测试用例的撰写. 也可以采用.md文件的格式.

def test_code_frm():
    code_frm_step = CodeFrmStep() # 这个为待实现的class
    input = pd.DataFrame(data = [['hi', 'class'], ['para', 'return'], [3,2,1]])
    expected_res =  pd.DataFrame(data =  [[3],[5]])
    res = code_frm_step.do(input) # 这个为待实现的方法    
    assert_frm(res, expected_res )

运行时间一般不超过5秒

  • 除了以下特殊情况:
  1. 网络爬虫的测试用例可能需要超过5秒,此时需要记录完善的日志,方便检查问题.
  2. 要进行含有robust文字的用来做鲁棒测试的用例.

测试用例拆分

  • 如果是用了同一个input来测试的话,合并到一个测试函数去.除了下面的特殊情况:
  • 如果是检查同一个方法的各个执行分支的话,可以使用写testcase的方式,在set_up中把input写好,然后写test_main_case, test_corner_case等方法来测试各个分支.

使用test_readme.py取代README.md.

  • 这个测试用例文件需要把模块中所有涉及到的步骤类跑一遍.
  • 需要在本文件顶部写上注释:包括核心概念解释.说明类与类之间的依赖关系.
  • 所有的核心概念需要在本文件中的测试用例中出现
  • 中间结果都需要记录日志(就保存在tests文件夹中).这样方便以后他人用这里的测试用例来排查问题.
# test_readme.py
"""
[核心概念] code_line: 不含有import的代码行数
class_line: 以class开头的行数
"""
def test_all():
    step_1 = Step1()
    step_2 = Step2()
    res1 = step_1.do()
    io_state.wirte(".tests/readme_res1.frm")
    res2 = step_2.do(res1)
    io_state.wirte(".tests/readme_res2.frm")
    expected_res = pd.DataFrame(data= [[1,2]])
    assert_frm(res2, expected_res) 

2018-08-21新增

测试用例所在的文件夹需要设置写权限给code reviewer

否则无法跑通文件读写相关的测试用例.

你可能感兴趣的:(ylib测试用例指引)