自動テストは、データ駆動型DDTである必要があります

前書き

  このように感じたことはありますか?自動テストのプロセスでは、API自動テストであろうとUI自動テストであろうと、テストスクリプトを作成する時間の大部分は、データの準備(setUp)とデータのクリーンアップ(tearDown)です。データは自動テストの重要な部分だからです。このように、データ駆動型は非常に重要です。次に共有するコンテンツは次のとおりです。DDT、Unittestテストフレームワークで一般的に使用されるデータ駆動型フレームワーク。

 

データ駆動型

1.データ駆動型とは何ですか?

  データ駆動型とは、自動テストでテストデータを処理する方法を指します。

  通常、テストデータは関数関数から分離され、関数関数の外部の場所に保存されます自動テストの実行中、データ駆動型フレームワークはデータソース内のデータを読み取り、そのデータをパラメーターとして関数関数に渡し、データの数に応じて同じ関数関数を複数回実行します

  データ駆動型データソースは、関数、CSVファイル、Excelテーブル、TXTファイル、およびデータベース以外のデータコレクションです。

 

2.データ駆動型の利点は何ですか?

  (1)繰り返しコードの削減
  次の例を通して、データ駆動型がどのように繰り返しコードを削減できるかを見てみましょう。

def test_001(user, pwd, num):
    # 实际函数逻辑
    pass

# 如果没有数据驱动,你的代码可能会是这样的:
test_001('one', 'test_one', 1)
test_001('two', 'test_two', 2)
test_001('three', 'test_three', 3)

  データドリブンを使用せず、同じ関数関数に対して複数のテストデータがある場合、この関数関数を複数回呼び出すことしかできません。さらに、特定のテストデータを変更/削除したら、対応する関数を変更する必要があります。関数呼び出しでのテストデータは非常に不便です。

  テスト駆動を使用する場合、コードは次のようになります。

# origin_data指向一个文件,这个文件里存储有你所有的测试数据。
origin_data = './tests/data/testdata.csv'

# dataDrivenDecorator是你实现数据驱动的装饰器

@dataDrivenDecorator(origin_data)
def test_001(user, pwd, num):
    # 实际函数逻辑
    pass

  この場合、複数の呼び出しを行う必要はなく、テストデータが変更された場合は、データソースファイルのデータを変更するだけで済みます。

 

  (2)データが属するテストケースの障害は、他のテストデータに対応するテストケースに影響を与えません。
  次の例を通して、他のテストデータに対応するテストケースがどのように影響を受けないかを見てみましょう。
  データ駆動型を使用しない場合は、次のいずれかの関数があると想定します。

test_data = [0, 1, 0, 1]
def test_001(data):
    for x in data:
        assert x > 0

test_001(test_data)

  

実行結果は下図のようになります。
画像

 

  実行結果から、test_dataの最初の値は0であるため、0以下であることがわかります。したがって、アサーションは失敗し、test_dataテストデータセットの0以降のすべてのテストデータは実行されません。

  データドライブがある場合、データドライブはこのテストをテストデータに従って複数のテストに分解するため、最初のテストデータが失敗しても、後続のテスト結果に影響はありません。

 

3. Pythonで広く使用されているデータ駆動型フレームワークは何ですか?

  • DDT(Data-Driven Tests)、通常はUnittestと組み合わせます

  • パラメータ化された、データ駆動型を実装するためにPytestで一般的に使用されるフレームワーク

     

DDTに含まれるデコレータ

1クラスのデコレータ

  ddtクラスデコレータはTestCaseのサブクラスでデコレートする必要があります。TestCaseはUnittestフレームワークの基本クラスであり、テスト操作を駆動するためにTestRunnerが必要とするインターフェイスを実装します。

 

2つのメソッドデコレータ

  それらは、dataとfile_dataです。
  データデコレータはテストデータを直接提供します
  。file_dataデコレータはJSONまたはYAMLファイルからテストデータをロードします。

 

DDTを使用する手順は次のとおりです。

  • @ddtを使用して、テストクラスを装飾します。

  • @dataまたは@file_dataを使用して、データ駆動型で必要なテストメソッドを装飾します。

  • テストデータのセットに複数のパラメーターがある場合は、解凍する必要があります。@ unpackを使用してテストメソッドを装飾します。

     

PythonインストールDDT:

  インストールコマンド:pip installddtまたはpython-m pip install ddt

 

DDTの使用

(1)、ddtはデータを直接提供します

from ddt import ddt, data, file_data, unpack
from selenium import webdriver
import unittest
import time

# ddt一定是装饰在TestCase的子类上

@ddt
class Baidu(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(30)
        self.base_url = "http://www.baidu.com/"

    # data表示测试数据是直接提供的。
    # unpack表示,对于每一组数据,如果它的值是list或者tuple,那么就分拆成独立的参数。

    @data(['Testing', 'Testing'], ['hello_world.com','Testing'])
    @unpack
    def test_baidu_search(self, search_string, expect_string):
        driver = self.driver
        driver.get(self.base_url + "/")
        driver.find_element_by_id("kw").send_keys(search_string)
        driver.find_element_by_id("su").click()
        time.sleep(2)
        search_results = driver.find_element_by_xpath('//*[@id="1"]/h3/a').get_attribute('innerHTML')
        print(search_results)
        self.assertEqual(expect_string in search_results, True)

    def tearDown(self):
        self.driver.quit()

if __name__ == "__main__":
    unittest.main(verbosity=2)

  この例では、@ dataデコレータを直接使用しました。このデコレータでは、テスト用に2セットのデータ、つまり['Testing'、 'Testing']と['hello_world.com'、 'Testing']を提供します。次に、@ unpackデコレータを使用してそれぞれのデータを配置します。データはパラメーターとして解凍され、関数test_baidu_searchに渡されます。

  上記のコードを実行すると、結果から、テストケースtest_baidu_searchは1つしかないことがわかります。しかし、生成されたテストレポートでは、「XXで2つのテストを実行」が表示されます。つまり、test_baidu_searchが2回実行されました。これは、DDTが機能していることです。

  これは、各グループに複数のパラメータセットと複数のデータがある場合です。各グループにデータが1つしかない場合はどうなりますか?以下を変更するだけです。

# 如仅有一个参数,那么直接在data里写参数就好。
# 仅有一个参数的情况下,无须再用@unpack装饰测试方法。
@data('data1', 'data2')

 

(2)、ddtは関数を使用してデータを提供します
  ddtはデータを直接提供します。ただし、上記の@data()のパラメーターにデータを直接書き込む場合を除き、別の状況があります。つまり、データは最初にデータを取得します。関数、そしてパラメータで@data()に書き込まれます。

from ddt import ddt, data, file_data, unpack
from selenium import webdriver
import unittest
import time

def get_test_data():
    # 这里写你获取测试数据的业务逻辑。

    # 获取到后,把数据返回即可。

    # 注意,如果多组数据,需要返回类似([数据1-参数1, 数据1-参数2],[数据2-参数1, 数据2-参数2])这样的格式,方便ddt.data()解析

    # 解析后返回的数据格式如下:
    results = (['Testing', 'Testing'], ['hello_world.com', 'Testing'])
    return results

# ddt一定是装饰在TestCase的子类上

@ddt
class Baidu(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(30)
        self.base_url = "http://www.baidu.com/"

    # data表示data是直接提供的。注意data里的参数我写了函数get_test_data()的返回值,并且以*为前缀,代表返回的是可变参数。

    # unpack表示,对于每一组数据,如果它的值是list或者tuple,那么就分拆成独立的参数。

    @data(*get_test_data())
    @unpack
    def test_baidu_search(self, search_string, expect_string):
        driver = self.driver
        driver.get(self.base_url + "/")
        driver.find_element_by_id("kw").send_keys(search_string)
        driver.find_element_by_id("su").click()
        time.sleep(2)
        search_results = driver.find_element_by_xpath('//*[@id="1"]/h3/a').get_attribute('innerHTML')
        print(search_results)
        self.assertEqual(expect_string in search_results, True)

    def tearDown(self):
        self.driver.quit()

if __name__ == "__main__":
    unittest.main(verbosity=2)

  上記の例では、テストデータを取得するための関数get_test_data()を作成しました。この関数は、ビジネスロジックに応じて、パラメーターを受け取ることも、パラメーターを受け取らないこともできます。

  注:get_test_data()の戻り値は、ddt.data()の許容可能なデータ形式に準拠している必要があります。

      つまり、データのセット、各データは単一の値、複数のデータのセット、データの各グループはリストまたは辞書です。

 

(3)ddtはファイルを使用してデータを提供します:
  @ddtを使用してJSONおよびYAMLのデータを直接提供することに加えて、DDTはファイルを介したデータのロードもサポートします。

  ただし、デフォルトではYAMLとJSONの2つの形式のみがサポートされており、「。yml」または「.yaml」で終わる形式のみがYAMLファイルと見なされ、その他の形式はJSONファイルと見なされます。

  上記のユースケースをJSONファイルを使用するように変更すると、ユースケースは次のようになり
画像ます。

  

     まず、test_baidu.pyと同じ名前のファイルtest_baidu.jsonを作成します。内容は次のとおりです。

{ "case1": {

  "search_string": "testing",

  "expect_string": "Testing"

  },

  "case2": {

  "search_string": "testing",

  "expect_string": "Testing"

  }

}

 

     次に、test_baidu.pyを更新します。更新されたコードは、次のとおりです。

from ddt import ddt, data, file_data, unpack
from selenium import webdriver
import unittest
import time

@ddt
class Baidu(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(30)
        self.base_url = "http://www.baidu.com/"

    # 此处测试数据从文件读取,使用@file_data装饰器

    # 文件路径是相对于Baidu这个测试类的相对路径

    # 使用外部文件方式Load数据无须使用unpack

    @file_data('test_baidu.json')
    def test_baidu_search(self, search_string, expect_string):
        driver = self.driver
        driver.get(self.base_url + "/")
        driver.find_element_by_id("kw").send_keys(search_string)
        driver.find_element_by_id("su").click()
        time.sleep(2)
        search_results = driver.find_element_by_xpath('//*[@id="1"]/h3/a').get_attribute('innerHTML')
        print(search_results)
        self.assertEqual(expect_string in search_results, True)

    def tearDown(self):
        self.driver.quit()

if __name__ == "__main__":
    unittest.main(verbosity=2)

 

ご覧のとおり、@ file_dataデコレータの使用は、@ dataデコレータの使用とは少し異なります。

  • @file_dataデコレータでは、ファイルのパスはテストクラス自体を基準にしています。この例では、テストクラスBaiduが配置されているファイルの相対位置です。

  • 同じデータセットに複数のパラメーターがある場合でも、@ file_dataを使用する場合はunpackを使用する必要はありません。

     

上記の例でYAMLファイルを使用する場合は、次の点に注意する必要があります。

  • Pythonでyamlファイルを使用する場合は、PyYAMLをインストールする必要があります。

  • インストールコマンド:pipinstallpyyamlまたはpython-m pip install pyyaml

     

インストール後、test_baidu.jsonの同じディレクトリに次の内容のファイルtest_baidu.yamlを作成します。

"case1":

  "search_string": "testing"

  "expect_string": "Testing"

"case2": 

  "search_string": "testing"

  "expect_string": "Testing"

次に、test_baidu.pyを変更します。変更されたコンテンツは、次のとおりです。

from ddt import ddt, data, file_data, unpack
from selenium import webdriver
import unittest
import time

# 使用yaml文件前先尝试导入,导入失败则将skip使用yaml数据驱动的测试用例

try:
    import yaml
except ImportError:
    have_yaml_support = False
else:
    have_yaml_support = True
    needs_yaml = unittest.skipUnless(
    have_yaml_support, "Need YAML to run this test"
)

@ddt
class Baidu(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(30)
        self.base_url = "http://www.baidu.com/"

    # 使用yaml文件必须使用@needs_yaml装饰

    @needs_yaml
    @file_data('test_baidu.yaml')
    def test_baidu_search(self, search_string, expect_string):
        driver = self.driver
        driver.get(self.base_url + "/")
        driver.find_element_by_id("kw").send_keys(search_string)
        driver.find_element_by_id("su").click()
        time.sleep(2)
        search_results = driver.find_element_by_xpath('//*[@id="1"]/h3/a').get_attribute('innerHTML')
        print(search_results)
        self.assertEqual(expect_string in search_results, True)

    def tearDown(self):
        self.driver.quit()

if __name__ == "__main__":
    unittest.main(verbosity=2)

  ご覧のとおり、JSONファイルを使用する場合とは異なり、YAMLファイルを使用するにはPyYamlを最初にインストールする必要があります。次に、yamlのインポートの失敗を防ぐために、needs_yamlデコレーターを定義して、プログラムに安全性の判断を追加しました。

      インポートが失敗した場合、needs_yamlで装飾されたすべてのテストケースは実行されません。

 

(4)ddtはファイルを使用してデータを提供します。ddtは
  デフォルトでJSONおよびYAML形式のデータのみをサポートするため、他の形式のデータファイルです。しかし、他のデータ形式を使用したい場合はどうなりますか?

  一般的に使用される方法は次の2つです。

  • 最初に他の形式(Excel形式など)でファイルを読み取り、次にddtでサポートされるJSONまたはYAMLファイルを作成し、最後に取得したデータをこのファイルに書き込んでから、@ file_data();を使用します。

  • 関数を作成し、他の形式でファイルを読み取り、関数でデータを取得して、@ ddt.data()でサポートされている形式にデータを直接返します。

 

[The Way of Infinite Testing]パブリックアカウントへの注目、[リソースの受信]への返信、
Pythonプログラミング学習リソースの乾物、
Python + AppiumフレームワークAPPUI自動化、
Python + Seleniumフレームワーク
WebUI自動化、Python + UnittestフレームワークAPIへようこそオートメーション、

リソースとコードは無料で送信されます〜
記事の下部に公式アカウントのQRコードがあります。WeChatでスキャンしてフォローするだけです。

備考:私の個人公開アカウントが正式に開設され、ビッグデータテスト、機能テスト、テスト開発、APIインターフェイスの自動化、テストの運用と保守、UI自動化テストなどのテストテクノロジーの共有に専念しています。WeChat検索パブリックアカウント:「WuliangThe Way of Testing」、または以下のQRコードをスキャンしてください。

 注意を向けて、一緒に成長しましょう!

おすすめ

転載: blog.csdn.net/weixin_41754309/article/details/113093496