$30 off During Our Annual Pro Sale. View Details »

Evidence

 Evidence

Tech talk on rannts#12 (Aug 12 2016) about problems, related to storing of test results.

Sergey Arkhipov

August 13, 2016
Tweet

More Decks by Sergey Arkhipov

Other Decks in Programming

Transcript

  1. Вещественные доказательства
    Сергей Архипов
    2016

    View Slide

  2. Что такое «плохой» коммит?

    View Slide

  3. View Slide

  4. View Slide

  5. View Slide

  6. View Slide

  7. View Slide

  8. View Slide

  9. Метаинформация
    ― Автор;
    ― Коммиттер;

    View Slide

  10. Метаинформация
    ― Автор;
    ― Коммиттер;
    ― Основной тикет в багтрекере;
    ― Релевантные тикеты в багтрекере;

    View Slide

  11. Метаинформация
    ― Автор;
    ― Коммиттер;
    ― Основной тикет в багтрекере;
    ― Релевантные тикеты в багтрекере;
    ― Результаты юнит-тестирования;
    ― Результаты функционального
    тестирования;
    ― Результаты статического анализа;

    View Slide

  12. Метаинформация
    ― Автор;
    ― Коммиттер;
    ― Основной тикет в багтрекере;
    ― Релевантные тикеты в багтрекере;
    ― Результаты юнит-тестирования;
    ― Результаты функционального
    тестирования;
    ― Результаты статического анализа;
    ― Кто ревьюил код и что сказал;
    ― Бэкпортированное ли изменение;

    View Slide

  13. Метаинформация
    ― Автор;
    ― Коммиттер;
    ― Основной тикет в багтрекере;
    ― Релевантные тикеты в багтрекере;
    ― Результаты юнит-тестирования;
    ― Результаты функционального
    тестирования;
    ― Результаты статического анализа;
    ― Кто ревьюил код и что сказал;
    ― Бэкпортированное ли изменение;
    ― Версия софта, где изменения,
    вызванные коммитом есть as is;
    ― Версия софта, где кто-то
    подправил изменения этого
    коммита.

    View Slide

  14. «Плохой» коммит
    с точки зрения тестирования

    View Slide

  15. Плохой коммит
    ― Процент прошедших тестов;
    ― Покрытие кода тестами;
    ― Результаты статического анализа;
    ― Результаты измерения цикломатической
    сложности;
    ― Результаты соответствия стилю
    кодирования.

    View Slide

  16. Плохой коммит
    ― Как формировать результат прохождения
    тестов;
    ― Как хранить результаты.

    View Slide

  17. Как формировать результаты

    View Slide

  18. tests/api/test_pagination.py::test_sort_by_fail[value0] PASSED
    tests/api/test_pagination.py::test_sort_by_fail[value1] PASSED
    tests/api/test_pagination.py::test_sort_by_fail[] PASSED
    tests/api/test_pagination.py::test_sort_by_fail[1] PASSED
    tests/api/test_pagination.py::test_sort_by_fail[11] PASSED
    tests/api/test_pagination.py::test_sort_by_fail[value5] PASSED
    tests/api/test_pagination.py::test_sort_by_fail[value6] PASSED
    tests/api/test_pagination.py::test_sort_by_fail[value7] PASSED
    tests/api/test_pagination.py::test_sort_by_fail[value8] PASSED
    tests/api/test_pagination.py::test_sort_by_fail[value9] PASSED
    tests/api/test_pagination.py::test_sort_by_fail[value10] PASSED
    tests/api/test_pagination.py::test_sort_by_fail[value11] PASSED
    tests/api/test_pagination.py::test_sort_by_fail[value12] PASSED
    tests/api/test_pagination.py::test_sort_by_ok PASSED
    tests/api/test_validators.py::test_require_schema_positive_integer_fail[-
    1] PASSED
    tests/api/test_validators.py::test_require_schema_positive_integer_fail[1]
    PASSED
    tests/api/test_validators.py::test_require_schema_positive_integer_fail[]
    PASSED
    tests/api/test_validators.py::test_require_schema_positive_integer_fail[va
    lue3] PASSED
    tests/api/test_validators.py::test_require_schema_positive_integer_fail[va
    lue4] PASSED
    tests/api/test_validators.py::test_require_schema_positive_integer_fail[No
    ne] PASSED

    View Slide

  19. skips="0" tests="32" time="0.412">
    classname="tests.api.views.v1.test_api_auth"
    file="tests/api/views/v1/test_api_auth.py" line="23"
    name="test_incorrect_login_data[None-text/html]"
    time="0.01604437828063965">
    2016-08-07 16:44:37 [ERROR ] (
    generic.py:50 ): <201d686e-ae96-4b8d-ae5f-
    f66b522b23fe> | Cannot process user request: 400:
    Bad Request


    View Slide

  20. Subunit (rtcollins)
    ― https://github.com/testing-cabal/subunit
    ― Протокол предоставления тестовых
    результатов;
    ― Представляет собой стрим, не конечный
    результат;
    ― Позволяет прикреплять аттачи к тестам;
    ― Мультиплексированный поток.

    View Slide

  21. import os
    import subprocess
    import unittest
    class MyTestCase(unittest.TestCase):
    def test_ls_command(self):
    process = subprocess.Popen(
    "slq", shell=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE)
    process.wait()
    self.assertEqual(
    process.returncode, os.EX_OK)

    View Slide

  22. ===========================================================
    FAIL: test_ls_command (testcase.MyTestCase)
    -----------------------------------------------------------
    Traceback (most recent call last):
    File "testcase.py", line 19, in test_ls_command
    process.returncode, os.EX_OK)
    AssertionError: 127 != 0
    -----------------------------------------------------------
    Ran 1 test in 0.002s
    FAILED (failures=1)

    View Slide

  23. import os
    import subprocess
    import testtools
    import testtools.content
    class MyTestCase(testtools.TestCase):
    def test_ls_command(self):
    process = subprocess.Popen(
    "slq", shell=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE)
    process.wait()
    self.addDetail(
    "ls-stdout",
    testtools.content.text_content(process.stdout.read()))
    self.addDetail(
    "ls-stderr",
    testtools.content.text_content(process.stderr.read()))
    self.assertEqual(
    process.returncode, os.EX_OK)

    View Slide

  24. ======================================================================
    FAIL: test_ls_command (testcase.MyTestCase)
    testcase.MyTestCase.test_ls_command
    ----------------------------------------------------------------------
    _StringException: Empty attachments:
    ls-stdout
    ls-stderr: {{{/bin/sh: 1: slq: not found}}}
    Traceback (most recent call last):
    File "testcase.py", line 28, in test_ls_command
    process.returncode, os.EX_OK)
    File "/home/nineseconds/.pyenv/versions/evidence/lib/python2.7/site-
    packages/testtools/testcase.py", line 411, in assertEqual
    self.assertThat(observed, matcher, message)
    File "/home/nineseconds/.pyenv/versions/evidence/lib/python2.7/site-
    packages/testtools/testcase.py", line 498, in assertThat
    raise mismatch_error
    testtools.matchers._impl.MismatchError: 127 != 0
    ----------------------------------------------------------------------
    Ran 1 test in 0.004s
    FAILED (failures=1)

    View Slide

  25. ➜ python -m subunit.run testcase.py
    �),#testcase.MyTestCase.test_ls_command +3W D `#testcase.MyTe
    ���� � ���
    stCase.test_ls_commandI +p@[W D r:0#testcase.MyTestCase.test_l
    ���� � ��
    s_commandtext/plain; charset="utf8" ls-
    stdout U +p@vW D r:0#testcase.MyTestCase.test_ls_commandtext/pla
    �� � � ��
    in; charset="utf8" ls-stderr/bin/sh: 1: slq: not found
    �` +`@ W D r:0#testcase.MyTestCase.test_ls_command3text/x-
    �� � � ��
    traceback; charset="utf8"; language="python" traceback#Traceback
    (most recent call last):
    !~ A +`@ W D r:0#testcase.MyTestCase.test_ls_command3text/x-
    � � � � ��
    traceback; charset="utf8"; language="python" traceback@T File
    "testcase.py", line 28, in test_ls_command
    process.returncode, os.EX_OK)

    View Slide

  26. ➜ python -m subunit.run testcase.py | subunit2pyunit
    testcase.MyTestCase.test_ls_command
    testcase.MyTestCase.test_ls_command ... FAIL
    ======================================================================
    FAIL: testcase.MyTestCase.test_ls_command
    testcase.MyTestCase.test_ls_command
    ----------------------------------------------------------------------
    _StringException: Empty attachments:
    ls-stdout
    ls-stderr: {{{/bin/sh: 1: slq: not found}}}
    Traceback (most recent call last):
    File "testcase.py", line 28, in test_ls_command
    process.returncode, os.EX_OK)
    File "/home/nineseconds/dev/experiments/evidence/.v/local/lib/python2.7/site-
    packages/testtools/testcase.py", line 411, in assertEqual
    self.assertThat(observed, matcher, message)
    File "/home/nineseconds/dev/experiments/evidence/.v/local/lib/python2.7/site-
    packages/testtools/testcase.py", line 498, in assertThat
    raise mismatch_error
    testtools.matchers._impl.MismatchError: 127 != 0
    ----------------------------------------------------------------------
    Ran 1 test in 0.001s
    FAILED (failures=1)

    View Slide

  27. ➜ python -m subunit.run testcase.py | subunit2junitxml


    Traceback (most
    recent call last):
    testtools.testresult.real._StringException: Empty attachments:
    ls-stdout
    ls-stderr: {{{/bin/sh: 1: slq: not found}}}
    Traceback (most recent call last):
    File "testcase.py", line 28, in test_ls_command
    process.returncode, os.EX_OK)
    File "/home/nineseconds/dev/experiments/evidence/.v/local/lib/python2.7/site-
    packages/testtools/testcase.py", line 411, in assertEqual
    self.assertThat(observed, matcher, message)
    File "/home/nineseconds/dev/experiments/evidence/.v/local/lib/python2.7/site-
    packages/testtools/testcase.py", line 498, in assertThat
    raise mismatch_error
    testtools.matchers._impl.MismatchError: 127 != 0



    View Slide

  28. Как хранить результаты

    View Slide

  29. testrepository (rtcollins)
    ― https://github.com/testing-cabal/testreposit
    ory
    ― Представляет репозиторий как вход для
    теста;
    ― Хранит результаты предыдущих запусков
    тестов в отдельной директории;
    ― Дает возможность посмотреть статистику,
    единообразно запустить тесты.

    View Slide

  30. git-test
    ― git-test хранит результаты в самом Git;
    ― Хранит метаинформацию о тестовом
    запуске. Понимает про то, что запуски
    могут быть разными;
    ― Результат тестового прогона можно
    добавить когда угодно;
    ― Трекает не поваленные тесты, а результаты
    тестирования на определенном коммите.

    View Slide

  31. .gittest
    {
    "default": {
    "command": "tox -e py27"
    },
    "tox": {
    "command": "tox"
    }
    }

    View Slide

  32. git test list tox
    # ---
    # tox
    # ---
    2016-07-06T16:21:15.930000 00999c29c0006d28964ed048c371a954ad5c9d30 passed
    2016-07-07T20:54:58.690000 039c4364c5b45a6f27f6aa97de4b1a3a8e9e4a1f passed
    2016-07-07T20:20:35.290000 5d2dfd6a8dfdcd42145245c80348677a8150caab passed
    2016-07-06T21:46:54.060000 607efc68cc081e304ded888f9405a9a5f0e2594a failed
    2016-07-06T18:16:59.890000 80b35b26729075c71de748810edd57ea86c850a8 passed
    2016-07-06T22:00:59.860000 a66e31ad4b3780f14c3748bd9c33eb38ebc85373 passed
    2016-07-06T10:51:21.210000 e6f5819d879c1c50d12fa919e13ef72c835d37a9 passed

    View Slide

  33. git test show
    # -------
    # default
    # -------
    Test command: tox -e py27
    Exit code: 0
    Start at: Thu Jul 7 20:54:52 2016 (1467914092.94)
    Finish at: Thu Jul 7 20:54:58 2016 (1467914098.68)
    Duration: 5 seconds
    Hostname: home-laptop
    User: nineseconds
    Environment:
    HISTTIMEFORMAT: %d.%m.%y %H:%M:%S
    LESS: -R

    SHLVL: 2
    PWD: /home/nineseconds/dev/pvt/git-test
    py27 recreate: /home/nineseconds/dev/pvt/git-test/.tox/py27
    py27 installdeps: -r/home/nineseconds/dev/pvt/git-test/requirements.txt,
    -r/home/nineseconds/dev/pvt/git-test/test-requirements.txt
    py27 installed: colorama==0.3.7,coverage==4.1,flake8==2.6.2,flake8-
    coding==1.2.2,funcsigs==1.0.2,hacking==0.11.0,mando==0.3.3,mccabe==0.5.0,mock==2.0.0,
    pbr==1.10.0,pep8==1.5.7,py==1.4.31,pycodestyle==2.0.0,pyflakes==1.2.3,pytest==2.9.2,p
    ytest-cov==2.3.0,PyYAML==3.11,radon==1.4.0,requests==2.10.0,six==1.10.0,xenon==0.4.0
    py27 runtests: PYTHONHASHSEED='0'
    py27 runtests: commands[0] | py.test --basetemp=/home/nineseconds/dev/pvt/git-
    test/.tox/py27/tmp -v
    ============================= test session starts ==============================

    View Slide

  34. git-test
    ― git-test хранит результаты рядом с
    коммитами, в git-notes; не требуется
    создания новых коммитов;
    ― Всегда известно, кто и при каких условиях
    протестировал коммит. Можно хранить
    subunit-стрим.
    ― Тестраны добавляются постфактум.
    ― Сделан одним скриптом без внешних
    зависимостей.

    View Slide

  35. Как обрабатывать результаты

    View Slide

  36. View Slide

  37. @9seconds   
    https:/
    /speakerdeck.com/9seconds/evidence

    View Slide