测试驱动开发(Test Driven Development)

单元测试在行业中#

单元测试框架:

https://en.wikipedia.org/wiki/List_of_unit_testing_frameworks

开源项目几乎都有单元测试:

https://github.com/django/django/actions/workflows/tests.yml

----------------------------------------------------------------------
Ran 17940 tests in 229.063s

https://github.com/psf/requests/actions/workflows/run-tests.yml

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
------ generated xml file: /home/runner/work/requests/requests/report.xml ------
====== 590 passed, 15 skipped, 1 xfailed, 18 warnings in 79.16s (0:01:19) ======

https://github.com/python/cpython/actions/workflows/build.yml

Total duration: 7 min 38 sec
Total tests: run=47,529 failures=1 skipped=2,067
Total test files: run=484/485 skipped=16 resource_denied=2 rerun=1
Result: FAILURE then SUCCESS

编码时遇到下面的问题应该怎样做?#

获取数组长度,下面哪种写法是正确的?

gc.get_objects(0).count()

...

len(gc.get_objects(0))

删除 None 会报错吗?

del None

避免猜测,先去求证#

在 Python Console 中进行测试:

>>> gc.get_objects(0).count()
Traceback (most recent call last):
  File "/Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevconsole.py", line 364, in runcode
    coro = func()
  File "<input>", line 1, in <module>
TypeError: list.count() takes exactly one argument (0 given)

>>> len(gc.get_objects(0))
467

>>> del None
Traceback (most recent call last):
  File "/Users/zja/.pyenv/versions/3.10.11/lib/python3.10/code.py", line 63, in runsource
    code = self.compile(source, filename, symbol)
  File "/Users/zja/.pyenv/versions/3.10.11/lib/python3.10/codeop.py", line 153, in __call__
    return _maybe_compile(self.compiler, source, filename, symbol)
  File "/Users/zja/.pyenv/versions/3.10.11/lib/python3.10/codeop.py", line 73, in _maybe_compile
    return compiler(source, filename, symbol)
  File "/Users/zja/.pyenv/versions/3.10.11/lib/python3.10/codeop.py", line 118, in __call__
    codeob = compile(source, filename, symbol, self.flags, True)
  File "<input>", line 1
    del None
        ^^^^
SyntaxError: cannot delete None

函数的逻辑是否正确?#

def check_gen2(*_args, **_kwargs):
    global gen2_objs
    gc.collect()
    new_gen2_objs = WeakSet(gc.get_objects(2))
    if gen2_objs is not None:
        new_objs = new_gen2_objs - gen2_objs
        print(new_objs)
        del gen2_objs
    gen2_objs = new_gen2_objs

真实代码验证#

  # 23aa9299
class TargetAnyDisplay:

    @staticmethod
    def is_support(define_id):
        return define_id == parameter_def.TARGET_ANY.define_id
        return define_id in (parameter_def.TARGET_ANY.define_id, parameter_def.SANDBOX_TARGET_ANY.define_id)

    @staticmethod
    def get_display_info(define_id):
        queryset = TargetMachine.objects.filter(type_id=TargetType.REAL, is_deleted=False)
        if define_id == parameter_def.SANDBOX_TARGET_ANY.define_id:
            queryset = queryset.filter(agent__source=AgentSource.Sandbox)
        resource_list = order_agent_list(queryset, TARGET_FIELDS)
        return get_agent_display_infos(resource_list, False)

测试代码如下:

@pytest.mark.django_db
def test_sandbox_agent_display_info():
    AreaMgt.objects.create(area='sandbox_area')
    agent = Agent.objects.create(name='sandbox_agent', source=AgentSource.Sandbox)
    target = TargetMachine.objects.create(name='sandbox_target', real_agent=agent, status=AgentStatus.ONLINE, area='sandbox_area', os_type=2)
    info = get_define_display_infos([parameter_def.SANDBOX_TARGET_ANY.define_id])
    assert info[parameter_def.SANDBOX_TARGET_ANY.define_id][0]['children'][0]['children'][0]['id'] == target.id
    assert info[parameter_def.SANDBOX_TARGET_ANY.define_id][0]['children'][0]['children'][0]['source'] == 2

Mock#

Pytest#

Django Test Database#

comments powered by Disqus