24
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

pyATSの初歩

Last updated at Posted at 2017-12-06

#pyATSとは
pyATS は、Python Automated Test Systems の略で、python3 ベースのテストフレームワークです。Cisco によって開発されています。license は、Apache 2.0 です。

Document などの情報は、以下のリンクにあります。
Cisco DevNet: pyATS

pytest のように、pythonプログラムのテストに使用できますが、Device object や ConnectionManager object という router 等の network device のテストをするための機能も含まれています。
この記事では、とりあえず pyATS の基本機能を動作させてみただけで、Device object などは使っていません。
pyATS で Cisco IOS Router にアクセスした事例は、 「pyATSによるCisco IOS Routerのテスト例」 に記載しています。
#インストール

環境

  • pyATS は、python 3.4 以上を必要とします。今回は、3.4.5を使いました。
  • python3 の development library が必要です。今回は、python34-devel.x86_64 を使いました。
  • CentOS7 上で動かしました。
  • pyATS は、4.0.0 を使用しています。
    なお、pyATS 4.0.0 は、Linux と Mac OS には対応していますが、Windows 系は未サポートとなっています。

##インストール方法
普通に pip でインストールできます。今回は、以下のように virtualenv で動かしています。

$ python3 -m virtualenv pyATS
$ cd pyATS
$ source bin/activate
$ pip install pyats

#テストをしてみる
##テスト対象
テスト対象として以下のようなクラスを使いました。

shape.py
#!/usr/bin/env python

class Shape(object):

    def __init__(self, name):
        self.name = name
        if name == 'triangle':
            self.sides = 3
        elif name == 'rectangle':
            self.sides = 4
        elif name == 'pentagon':
            self.sides = 6
        else:
            self.sides = 0

##テストスクリプトの構造
テストスクリプトは、ats.aetest モジュールの Class を使って記述します。
pyATS では、スクリプトは以下のような構造になっています。

  • 0または1個の CommonSetup Class
  • 1個以上の Testcase Class
  • 0または1個の CommonCleanup Class

CommonSetup と CommonCleanup は、複数の subsection を method として持ちます。

Testcase は更に以下の sub section に分かれます。

  • 0または1個の setup method
  • 1個以上の test method
  • 0または1個の cleanup method

それぞれ、@setup, @test, @cleanup decoratorを使って修飾することで、その subsection と aetest に認識されます。

pyATS を実行すると最初に CommonSetup が実行され、その次に Testcase が記述された順番で実行されます。最後に、CommonCleanup が実行されます。
ats.aetest は、各セクション毎に、実行結果をレポートする機能ももっています。

##テストスクリプトの例
Shape class をテストするテストケースを書いてみます。
Testcase classのみを使います。
name が triangle, rectangle, pentagon の Shape object を作って、sides の値が正しいかをcheckします。
pentagon の時には、間違った sides が設定されるので、そのケースは fail になるはずです。

simple_test.py
from ats import aetest
from shape import Shape

# test section within Testcases
class Testcase(aetest.Testcase):

    # define test section by applying @test decorator
    @aetest.test
    def testcase_one(self):
        shape = Shape('triangle')
        assert(shape.sides == 3)

    @aetest.test
    def testcase_two(self):
        shape = Shape('rectangle')
        assert(shape.sides == 4)

    @aetest.test
    def testcase_three(self):
        shape = Shape('pentagon')
        assert(shape.sides == 5)

##実行方法
前記のテストスクリプトの最後で、ats.aetest.main() を実行すれば、テストを実行できます。今回は、以下のような wrapper を作成して、任意のスクリプトを実行できるようにしました。

run_test.py
#!/usr/bin/env python
from ats.aetest import main
import sys

testscript = sys.argv[1]
main(testable = testscript)

以下のようにして、simple_test.py を実行します。

$ ./run_test.py simple_test.py

##実行結果
結果は、以下のようになります。
testcase_three で fail が発生しています。

2017-12-06T23:53:14: %AETEST-INFO: Starting testcase Testcase
./run_test.py:6: DeprecationWarning: Starting v3.0.0, section.id is deprecated and replaced by section.uid. Please modify your scripts. This will be removed next release
  main(testable = testscript)
2017-12-06T23:53:14: %AETEST-INFO: Starting section testcase_one
2017-12-06T23:53:14: %AETEST-INFO: The result of section testcase_one is => PASSED
2017-12-06T23:53:14: %AETEST-INFO: Starting section testcase_two
2017-12-06T23:53:14: %AETEST-INFO: The result of section testcase_two is => PASSED
2017-12-06T23:53:14: %AETEST-INFO: Starting section testcase_three
2017-12-06T23:53:14: %AETEST-WARNING: An assertion failure was caught:
2017-12-06T23:53:14: %AETEST-WARNING: Traceback (most recent call last):
2017-12-06T23:53:14: %AETEST-WARNING:   File "/home/tokatsu/pyATS/myCases/simple_case/simple_test.py", line 21, in testcase_three
2017-12-06T23:53:14: %AETEST-WARNING:     assert(shape.sides == 5)
2017-12-06T23:53:14: %AETEST-WARNING: AssertionError
2017-12-06T23:53:14: %AETEST-INFO: The result of section testcase_three is => FAILED
2017-12-06T23:53:14: %AETEST-INFO: The result of testcase Testcase is => FAILED
2017-12-06T23:53:14: %AETEST-INFO: +------------------------------------------------------------------------------+
2017-12-06T23:53:14: %AETEST-INFO: |                               Detailed Results                               |
2017-12-06T23:53:14: %AETEST-INFO: +------------------------------------------------------------------------------+
2017-12-06T23:53:14: %AETEST-INFO:  SECTIONS/TESTCASES                                                      RESULT
2017-12-06T23:53:14: %AETEST-INFO: --------------------------------------------------------------------------------
2017-12-06T23:53:14: %AETEST-INFO: .
2017-12-06T23:53:14: %AETEST-INFO: `-- Testcase                                                             FAILED
2017-12-06T23:53:14: %AETEST-INFO:     |-- testcase_one                                                     PASSED
2017-12-06T23:53:14: %AETEST-INFO:     |-- testcase_two                                                     PASSED
2017-12-06T23:53:14: %AETEST-INFO:     `-- testcase_three                                                   FAILED
2017-12-06T23:53:14: %AETEST-INFO: +------------------------------------------------------------------------------+
2017-12-06T23:53:14: %AETEST-INFO: |                                   Summary                                    |
2017-12-06T23:53:14: %AETEST-INFO: +------------------------------------------------------------------------------+
2017-12-06T23:53:14: %AETEST-INFO:  Number of ABORTED                                                            0
2017-12-06T23:53:14: %AETEST-INFO:  Number of BLOCKED                                                            0
2017-12-06T23:53:14: %AETEST-INFO:  Number of ERRORED                                                            0
2017-12-06T23:53:14: %AETEST-INFO:  Number of FAILED                                                             1
2017-12-06T23:53:14: %AETEST-INFO:  Number of PASSED                                                             0
2017-12-06T23:53:14: %AETEST-INFO:  Number of PASSX                                                              0
2017-12-06T23:53:14: %AETEST-INFO:  Number of SKIPPED                                                            0
2017-12-06T23:53:14: %AETEST-INFO: --------------------------------------------------------------------------------

#Loopを使ってみる
同じようなテストケースを3回書くのは冗長なので、pyATS の loop 機能を使って前記のスクリプトを書き直してみました。
##Loop を使った Testcase
Loop を実行するには、@loop decorator を使います。@loop の中で指定した loop parameter を順に使って、loop を実行します。

simple_test_loop.py
from ats import aetest
from shape import Shape

# test section within Testcases
class Testcase(aetest.Testcase):

    # define test section by applying @test decorator
    @aetest.loop(name = ['triangle', 'rectangle', 'pentagon'], sides = [3, 4, 5])
    @aetest.test
    def testcase_one(self, name, sides):
        shape = Shape(name)
        assert(shape.sides == sides)

##実行結果
test methond の名前以外は、simple_test.py と同じ結果になります。
method の名前は、元の名前に loop parameter の値を連結したものになります。

2017-12-07T00:00:33: %AETEST-INFO: Starting testcase Testcase
./run_test.py:6: DeprecationWarning: Starting v3.0.0, section.id is deprecated and replaced by section.uid. Please modify your scripts. This will be removed next release
  main(testable = testscript)
2017-12-07T00:00:33: %AETEST-INFO: Starting section testcase_one[name=triangle,sides=3]
2017-12-07T00:00:33: %AETEST-INFO: The result of section testcase_one[name=triangle,sides=3] is => PASSED
2017-12-07T00:00:33: %AETEST-INFO: Starting section testcase_one[name=rectangle,sides=4]
2017-12-07T00:00:33: %AETEST-INFO: The result of section testcase_one[name=rectangle,sides=4] is => PASSED
2017-12-07T00:00:33: %AETEST-INFO: Starting section testcase_one[name=pentagon,sides=5]
2017-12-07T00:00:33: %AETEST-WARNING: An assertion failure was caught:
2017-12-07T00:00:33: %AETEST-WARNING: Traceback (most recent call last):
2017-12-07T00:00:33: %AETEST-WARNING:   File "/home/tokatsu/pyATS/myCases/simple_case/simple_test_loop.py", line 12, in testcase_one
2017-12-07T00:00:33: %AETEST-WARNING:     assert(shape.sides == sides)
2017-12-07T00:00:33: %AETEST-WARNING: AssertionError
2017-12-07T00:00:33: %AETEST-INFO: The result of section testcase_one[name=pentagon,sides=5] is => FAILED
2017-12-07T00:00:33: %AETEST-INFO: The result of testcase Testcase is => FAILED
2017-12-07T00:00:33: %AETEST-INFO: +------------------------------------------------------------------------------+
2017-12-07T00:00:33: %AETEST-INFO: |                               Detailed Results                               |
2017-12-07T00:00:33: %AETEST-INFO: +------------------------------------------------------------------------------+
2017-12-07T00:00:33: %AETEST-INFO:  SECTIONS/TESTCASES                                                      RESULT
2017-12-07T00:00:33: %AETEST-INFO: --------------------------------------------------------------------------------
2017-12-07T00:00:33: %AETEST-INFO: .
2017-12-07T00:00:33: %AETEST-INFO: `-- Testcase                                                             FAILED
2017-12-07T00:00:33: %AETEST-INFO:     |-- testcase_one[name=triangle,sides=3]                              PASSED
2017-12-07T00:00:33: %AETEST-INFO:     |-- testcase_one[name=rectangle,sides=4]                             PASSED
2017-12-07T00:00:33: %AETEST-INFO:     `-- testcase_one[name=pentagon,sides=5]                              FAILED
2017-12-07T00:00:33: %AETEST-INFO: +------------------------------------------------------------------------------+
2017-12-07T00:00:33: %AETEST-INFO: |                                   Summary                                    |
2017-12-07T00:00:33: %AETEST-INFO: +------------------------------------------------------------------------------+
2017-12-07T00:00:33: %AETEST-INFO:  Number of ABORTED                                                            0
2017-12-07T00:00:33: %AETEST-INFO:  Number of BLOCKED                                                            0
2017-12-07T00:00:33: %AETEST-INFO:  Number of ERRORED                                                            0
2017-12-07T00:00:33: %AETEST-INFO:  Number of FAILED                                                             1
2017-12-07T00:00:33: %AETEST-INFO:  Number of PASSED                                                             0
2017-12-07T00:00:33: %AETEST-INFO:  Number of PASSX                                                              0
2017-12-07T00:00:33: %AETEST-INFO:  Number of SKIPPED                                                            0
2017-12-07T00:00:33: %AETEST-INFO: --------------------------------------------------------------------------------
24
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?