pytestの簡単な勉強


  • pytestの簡単な学習
  • 一、紹介とダウンロードインストール
  • 二、基礎ユニットテスト(assert断言)
  • 1、試験関数の例
  • 2、試験クラスの例
  • 3、試験サンプル
  • の作成方法
  • 三、fixtureメソッド
  • 1、fixture単純例
  • 2、3種類の呼び出しfixture方式
  • テスト関数ダイレクトコール
  • はmarkを通過する.usefixtures()呼び出し
  • autouse呼び出し
  • 3、fixture戻り値
  • 4、テストデータベース接続の例
  • 5、テストファイル書き込みの例
  • 四、mark類
  • 1、簡単な-m
  • 2、一意ID実行
  • 3、簡単な-k
  • 4、登録マーク
  • 五、hook類(留坑)
  • 六、objects(ピットを残す)
  • 7、さらに

  • pytestの簡単な勉強


    一、紹介とダウンロードインストール

  • pytestはpythonのユニットテストフレームワークであり、pythonが持参したunittestテストフレームワークと類似しているが、unittestフレームワークよりも簡潔で効率的である.
  • それは主にassert断言を用いてユニット方法の記憶性テスト
  • を行う.
  • fixtureクラスがあり、リソースの占有量を減らすことができ、リソースの統一スケジューリング
  • 取付:pip install -U pytest
  • 試験:py.test --versionまたはpytest --version
  • 二、基礎ユニットテスト(assert断言)

  • assert断言python標準文法の中のもの
  • assetの後にブール値を返す式
  • が真であれば、通過する.偽であれば、異常
  • を投げ出す
    # example
    >>>assert 1 == 1
    >>>assert 2+2 == 2*2
    >>>assert len('hello') < 10
    >>>assert len('hello') > 10
    Traceback (most recent call last):
      File "", line 1, in 
    AssertionError
    >>>assert len('hello') > 10, ' 10'
    Traceback (most recent call last):
      File "", line 1, in 
    AssertionError:  10
    >>>assert range(4) == [0,1,2,3]

    上記のassertの例から,ユニットテストに適していることがわかる.

    1、テスト関数の例

    def func(x):
        return x+1
    
    def test_func():
        assert func(3) == 5

    端末に入り、そのファイルが存在するディレクトリの下でpytestを実行する.実行結果は次のとおりです.
    ========================= test session starts =========================
    platform linux2 -- Python 2.7.13+, pytest-3.7.4, py-1.6.0, pluggy-0.7.1
    rootdir: /home/light/code/study/test_pytest, inifile:
    plugins: celery-4.2.1
    collected 1 item                                                                                                        
    
    test_pytest.py F                                                                                                  [100%]
    
    ========================= FAILURES =========================
    _________________________ test_func ________________________
    
        def test_func():
    >       assert func(3) == 5
    E       assert 4 == 5
    E        +  where 4 = func(3)
    
    test_pytest.py:6: AssertionError
    ========================= 1 failed in 0.39 seconds =========================
    

    pytestは現在のディレクトリの下で、testで始まるファイル(つまりテストファイル)を探し、テストファイルを見つけたら、テストファイルに入ってtest_を探します.最初のテスト関数を実行します.上記のテスト出力により、このテスト中にテスト関数が収集され、テスト結果が失敗(Fとマークされている)し、FAILURES部分に詳細なエラー情報が出力され、テストの原因を分析するのに役立ち、「assert func(3)==5」という文がエラーになりました.エラーの原因はfunc(3)=4です.

    2、テストクラスの例

    
    class TestClass:
        def test_one(self):
            x = "this"
            assert 'h' in x
    
        def test_two(self):
            x = "hello"
            assert hasattr(x, 'check')

    端末に入り、そのファイルが存在するディレクトリの下でpytestを実行する.実行結果は次のとおりです.
    ========================= test session starts =========================
    platform linux2 -- Python 2.7.13+, pytest-3.7.4, py-1.6.0, pluggy-0.7.1
    rootdir: /home/light/code/study/test_pytest, inifile:
    plugins: celery-4.2.1
    collected 3 items                                                                                                       
    
    test_pytest.py ..F                                                                                                [100%]
    
    ========================= FAILURES =========================
    ________________________ TestClass.test_three ________________________
    
    self = 0x7f9371aa09d0>
    
        def test_three(self):
            x = 'world'
    >       assert hasattr(x, 'hello')
    E       AssertionError: assert False
    E        +  where False = hasattr('world', 'hello')
    
    test_pytest.py:20: AssertionError
    ========================= 1 failed, 2 passed in 0.14 seconds =========================

    pytestは現在のディレクトリの下で、testで始まるファイル(すなわちテストファイル)を探し、テストファイルを見つけた後、テストファイルに入ってTestで始まるテストクラスを探して実行します.上記のテスト結果を見ると、3つのテスト関数が採集されていることがわかります.そのうち、最初の2つは成功(.表示)、最後の1つは失敗(F表示)、FAILURES部分を見ると、False=hasattr(‘world’,‘hello’)、つまり‘world’に‘hello’属性がないので、エラーが表示されます.

    3、テストサンプルの作成方法


    前の2つの例を通して、いくつかの法則を見ることができます.-一般的には、テストファイルがあるフォルダでpytestを実行するだけでテストを開始できます.テストファイルはtest_先頭または_test末尾-test_で関数をテスト先頭-テストクラスはTestで始まり、__はありません.init__メソッド-assertの使用を断言-以上の条件を満たすとpytestは直接テスト例を実行できます.

    三、fixture方法

  • pytestのfixtureメソッドは、それ自体が装飾器として理解され、それは関数を装飾し、装飾後の関数はテスト関数(test_先頭の関数)によってパラメータとして使用することができる.
  • 例を挙げると、あるファイルを開きfixtureで飾る関数機能があります.他のテスト関数は、開くファイル関数をパラメータとして入力し、ファイルを直接使用できます.
  • 上記の例ではfixtureをリソースと見なすことができ、テスト用例が実行される前にこれらのリソースを構成する必要があり、実行後にリソースを解放する必要があります.
  • fixtureメソッドにより、リソースの呼び出しを低減し、scope、autouseなどのパラメータを構成することで、テストプロセスをより簡素化できます.
  • fixtureメソッドプロトタイプ:def fixture(scope="function", params=None, autouse=False, ids=None, name=None):
  • 1、fixture簡単な例

    import pytest
    
    @pytest.fixture()
    def before():
        print '
    before each test'
    def test_1(before): print 'test_1()' def test_2(before): print 'test_2()' assert 0

    上のコードはfixtureメソッドでbefore関数を装飾し、before関数は1行のデータを印刷します.2つのテスト関数のパラメータにbeforeがあります.
    端末に入り、そのファイルが存在するディレクトリの下でpytest -v -sを実行する.(備考:-vは結果.PASEDにマッピングし、FをFAILEDにマッピングする、-sはコードプロセスを実行することを指す)
    ========================= test session starts =========================
    platform linux2 -- Python 2.7.13+, pytest-3.7.4, py-1.6.0, pluggy-0.7.1 -- /home/light/.virtualenvs/study/bin/python2.7
    cachedir: .pytest_cache
    rootdir: /home/light/code/study/test_pytest, inifile:
    plugins: celery-4.2.1
    collected 2 items                                                                                          
    
    test_pytest.py::test_1 
    before each test
    test_1()
    PASSED
    test_pytest.py::test_2 
    before each test
    test_2()
    FAILED
    
    ========================= FAILURES =========================
    ________________________ test_2 ________________________
    
    before = None
    
        def test_2(before):
            print 'test_2()'
    >       assert 0
    E       assert 0
    
    test_pytest.py:15: AssertionError
    ========================= 1 failed, 1 passed in 0.03 seconds =========================

    結果から、2つのテスト関数が実行前に1行のデータを印刷していることがわかります.この例は意味がないかもしれませんが、before関数がファイルを開いたりsessionを開いたりすると、テスト関数が直接使用できます.

    2、3種類の呼び出しfixture方式


    テスト関数の直接呼び出し


    markを通るusefixtures()呼び出し

    import pytest
    
    @pytest.fixture()
    def before():
        print('
    before each test'
    ) @pytest.mark.usefixtures("before") def test_1(): print('test_1()') @pytest.mark.usefixtures("before") def test_2(): print('test_2()') class Test1: @pytest.mark.usefixtures("before") def test_3(self): print('test_1()') @pytest.mark.usefixtures("before") def test_4(self): print('test_2()') @pytest.mark.usefixtures("before") class Test2: def test_5(self): print('test_1()') def test_6(self): print('test_2()')

    Autouseで呼び出す

    import time
    import pytest
    
    @pytest.fixture(scope="module", autouse=True)
    def mod_header(request):
        print('
    -----------------'
    ) print('module : %s' % request.module.__name__) print('-----------------') @pytest.fixture(scope="function", autouse=True) def func_header(request): print('
    -----------------'
    ) print('function : %s' % request.function.__name__) print('time : %s' % time.asctime()) print('-----------------') def test_one(): print('in test_one()') def test_two(): print('in test_two()')

    Autouseは直訳して自動的に呼び出され、scopeと協力する必要があります.-fixtureメソッドプロトタイプ:def fixture(scope="function", params=None, autouse=False, ids=None, name=None): scopeは範囲を表し、autouseは自動呼び出しの有無を表します.-scope
    function: test , function scope
    classclass test 
    modulemodule test 
    session: session , session pytest , 

    3、fixture戻り値


    上記の例では、fixtureの戻り値はデフォルトNoneであり、fixtureに必要なものを返すように選択することができます.fixtureでデータを構成したり、ファイルを読んだり、データベースに接続したりする必要がある場合は、fixtureにこれらのデータやリソースを返すことができます.
    パラメータfixtureをどのように持つかはパラメータも持つことができ、パラメータをparamsに割り当てることができ、デフォルトはNoneです.paramの各値についてfixtureは実行を呼び出し、forループを実行するようにparamsの値を1回遍歴します.test_fixture_param.py
    import pytest
    
    @pytest.fixture(params=[1, 2, 3])
    def test_data(request):
        return request.param
    
    def test_not_2(test_data):
        print('test_data: %s' % test_data)
        assert test_data != 2
    ========================= test session starts =========================
    platform linux2 -- Python 2.7.13+, pytest-3.7.4, py-1.6.0, pluggy-0.7.1 -- /home/light/.virtualenvs/study/bin/python2.7
    cachedir: .pytest_cache
    rootdir: /home/light/code/study/test_pytest, inifile:
    plugins: celery-4.2.1
    collected 3 items                                                                                         
    
    test_param.py::test_not_2[1] test_data: 1
    PASSED
    test_param.py::test_not_2[2] test_data: 2
    FAILED
    test_param.py::test_not_2[3] test_data: 3
    PASSED
    
    ========================= FAILURES =========================

    3つのパラメータがそれぞれ実行されていることがわかります.

    4、テストデータベース接続の例

    # -*-coding:utf-8 -*-
    #  
    #  Models.py
    
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, Integer, String
    
    
    Base = declarative_base()
    
    
    class User(Base):
        __tablename__ = 'User'
        id = Column('id', Integer, primary_key=True, autoincrement=True)
        name = Column('name', String(50), unique=True)
        age = Column('age', Integer)
    
        def __repr__(self):
            return "" % (
                self.id, self.name, self.age)
    
    
    class Role(Base):
        __tablename__ = 'Role'
        id = Column('id', Integer, primary_key=True, autoincrement=True)
        name = Column('name', String(50), unique=True)
    
        def __repr__(self):
            return "" % (self.id, self.name)
    # -*-coding:utf-8 -*-
    # fixture , 
    
    # -*- coding:utf-8 -*-
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker
    from Models import Base, User, Role
    import pytest
    
    
    @pytest.fixture(scope='module', autouse=True)
    def connect():
        """
         , session 
         pytest 
        """
        print('conn...')
        conn_str = 'mysql+mysqlconnector://root:password@localhost:3306/pytest'
        engine = create_engine(conn_str, echo=True)
        db_session = sessionmaker(bind=engine)
        Base.metadata.create_all(engine)
        session = db_session()
        return session
    
    
    @pytest.fixture(scope='function', autouse=True)
    def start_test():
        print('
    start test...'
    ) def test_delete_data(connect): """ fixture""" session = connect session.query(User).delete() session.query(Role).delete() assert session.query(User).all() == [] assert session.query(Role).all() == [] def test_add_data(connect): u1 = User(name='Light', age=2) u2 = User(name='Ash', age=20) r = Role(name='user') session = connect session.add(u1) session.add(u2) session.add(r) session.commit() assert session.query(User).all() != [] assert session.query(Role).all() != [] def test_select_data(connect): session = connect data1 = session.query(User).filter(User.id == '1').first() data2 = session.query(User).filter(User.id == '2').first() data3 = session.query(Role).filter(Role.id == '1').first() assert data1.name == 'Light' and data1.age == 23 assert data2.name == 'Ash' and data2.age == 20 assert data3.name == 'user' def test_drop_table(connect): session = connect session.execute("drop table User") session.execute("drop table Role") assert session.execute('show tables').rowcount == 0

    上のコードに注意して、fixtureはmoduleレベルのautouse=Trueを使用しています.実行した結果、最初のテストをしたときだけデータベースに接続され、その後データベースに接続されていないことがわかります.
    端末対応フォルダに入りpytest-v test_を実行session.py
    ========================= test session starts =========================
    platform linux2 -- Python 2.7.13+, pytest-3.7.4, py-1.6.0, pluggy-0.7.1 -- /home/light/.virtualenvs/study/bin/python2.7
    cachedir: .pytest_cache
    rootdir: /home/light/code/study/test_pytest, inifile:
    plugins: celery-4.2.1
    collected 4 items                                                                                         
    
    test_session.py::test_delete_data PASSED             [  25%]
    test_session.py::test_add_data PASSED                [  50%]
    test_session.py::test_select_data PASSED             [  75%]
    test_session.py::test_drop_table PASSED              [ 100%]
    
    ========================= 4 passed in 1.06 seconds =========================

    5、テストファイルの書き込み例

    import pytest
    
    
    @pytest.fixture(scope='module', autouse=True)
    def openfile():
        print('open the file...')
        f = open('test.txt', 'a')
        return f
    
    
    def test_write1(openfile):
        f = openfile
        old_tell = f.tell()
        data = '1111111111
    '
    f.write(data) new_tell = f.tell() assert new_tell - old_tell == len(data) def test_write2(openfile): f = openfile old_tell = f.tell() data = '2222222222
    '
    f.write(data) new_tell = f.tell() assert new_tell - old_tell == len(data) def test_close(openfile): openfile.close() with pytest.raises(ValueError) as e: openfile.write('3')
    pytest -v -s test_file.py
    =========================================== test session starts ===========================================
    platform linux2 -- Python 2.7.13+, pytest-3.7.4, py-1.6.0, pluggy-0.7.1 -- /home/light/.virtualenvs/study/bin/python2.7
    cachedir: .pytest_cache
    rootdir: /home/light/code/study/test_pytest, inifile:
    plugins: celery-4.2.1
    collected 3 items                                                                                         
    
    test_file.py::test_write1 open the file...
    PASSED
    test_file.py::test_write2 PASSED
    test_file.py::test_close PASSED
    
    ======================================== 3 passed in 0.07 seconds =========================================

    ファイルが一度だけ開いているのが見えます.

    四、mark類

  • markはタグであり、装飾器としても理解できる.コマンドラインパラメータで特定のテスト関数を指定して実行できます.
  • ここでpytestのコマンドラインパラメータについて説明します.pytestコマンドラインのパラメータは非常に多く、前述した-v(結果.をPASSEDにマッピングし、FをFAILEDにマッピングする)と-s(コードプロセスの実行を指す)について説明した.ここでまず-mと-kについて話します.
  • すなわち、markクラスの主な役割は、各テスト関数が
  • を実行するかどうかを制御することである.

    1、簡単な-m

    import pytest
    
    
    @pytest.mark.a
    def test_a_1():
        print('this is a')
    
    
    @pytest.mark.a
    def test_a_2():
        print('this is a')
    
    
    @pytest.mark.b
    def test_b_1():
        print('this is b')

    上のコードには、それぞれ2つのaテスト、1つのbテストが表示されています.
    `pytest -v test_mark1.py -m a`
    ...
    collected 3 items / 1 deselected
    test_mark1.py::test_a_1 PASSED              [ 50%]
    test_mark1.py::test_a_2 PASSED              [100%]
    ...
    
    `pytest -v test_,ark1.py -m b`
    ...
    collected 3 items / 2 deselected
    test_mark1.py::test_b_1 PASSED              [100%]
    ...

    -mの後に指定した文字がタグに対応してテスト関数を実行することがわかります.
    `pytest -v test_mark1.py -m "not a"`
    ...
    collected 3 items / 2 deselected
    test_mark1.py::test_b_1 PASSED              [100%]
    ...
    `pytest -v test_mark1.py -m "not b"`
    ...
    collected 3 items / 1 deselected
    test_mark1.py::test_a_1 PASSED              [ 50%]
    test_mark1.py::test_a_2 PASSED              [100%]
    ...
    `pytest -v test_mark1.py -m "a or b"`
    ...
    collected 3 items
    test_mark1.py::test_a_1 PASSED              [ 33%]
    test_mark1.py::test_a_2 PASSED              [ 66%]
    test_mark1.py::test_b_1 PASSED              [100%]
    ...
    `pytest -v test_mark1.py -m "a and b"`
    ...
    collected 3 items / 3 deselected
    ...

    上記のコマンドライン実行後の結果からpytest-mの後のパラメータが論理的に判断できることがわかる(not,and,or).これは重要です.-kもそうですから.

    2、一意ID実行


    テスト関数を1つだけ実行したいと仮定し、それ以外は実行しない場合は、コマンドラインで指定できます.pytest -v test_mark1.py::test_a_1
    `pytest -v test_mark1.py::test_a_1`
    ...
    collected 1 item
    test_mark1.py::test_a_1 PASSED               [100%]
    ...

    3、簡単な-k


    kはkeyword,テスト関数のキーワードを指す.markタグテスト関数を使用しないと仮定すると、-kで直接テストしたい関数の名前または一部の名前を指定することもできます.
    `pytest -v test_mark1.py -k a_`
    ...
    collected 3 items / 1 deselected
    test_mark1.py::test_a_1 PASSED               [ 50%]
    test_mark1.py::test_a_2 PASSED               [100%]
    ...
    `pytest -v test_mark1.py -k "a_ or b_"`
    ...
    collected 3 items
    test_mark1.py::test_a_1 PASSED               [ 33%]
    test_mark1.py::test_a_2 PASSED               [ 66%]
    test_mark1.py::test_b_1 PASSED               [100%]
    ...
    `pytest -v test_mark1.py -k "not a_"`
    ...
    collected 3 items / 2 deselected
    test_mark1.py::test_b_1 PASSED               [100%]
    ...

    −mの使用を理解し,−kのパラメータも論理的に判断できる.

    4、登録マーク


    五、hook類(留坑)


    六、objects(ピットを残す)


    七、もっと