Common mock by moto in Python Unittest

1. Motivation

I thought that it would be redundant to create a mock with each test code while creating the test code, so I tried and errored to see if it could be shared. Below is a sample app and sample test code at the start. Make the EC2 creation part of the test code common.

--App: Acquires and outputs EC2 information

app.py


import boto3


def main():
    client = boto3.client('ec2')
    #Get all instance information.
    instances = client.describe_instances()
    #Extract the instance name.
    instace_name = [instance['KeyName'] for r in instances.get('Reservations') for instance in r.get('Instances')]
    #Output instance name
    print(instace_name)

--Test code: Create EC2 with mock and run the app

test.py


import unittest
import boto3
from moto import mock_ec2
from app import app


class MyTestCase(unittest.TestCase):
    @mock_ec2
    def test_case_1(self):
        client = boto3.client('ec2')
        #Set the conditions for EC2 to be created
        ec2objects = [
            {'KeyName': 'test_ec2_name_1'}
        ]
        #Create EC2
        for o in ec2objects:
            client.run_instances(
                ImageId='ami-03cf127a',
                MinCount=1,
                MaxCount=1,
                KeyName=o.get('KeyName'))
        #Run the app
        app.main()

    @mock_ec2
    def test_case_2(self):
        client = boto3.client('ec2')
        #Set the conditions for EC2 to be created
        ec2objects = [
            {'KeyName': 'test_ec2_name_2'}
        ]
        #Create EC2
        for o in ec2objects:
            client.run_instances(
                ImageId='ami-03cf127a',
                MinCount=1,
                MaxCount=1,
                KeyName=o.get('KeyName'))
        #Run the app
        app.main()


if __name__ == '__main__':
    unittest.main()

2. Try using the setUp method

Write the code to create EC2 in the setUp method and try to create EC2 before executing the test case.

test.py


import unittest
import boto3
from moto import mock_ec2
from app import app


class MyTestCase(unittest.TestCase):
    @mock_ec2
    def setUp(self):
        client = boto3.client('ec2')
        #Set the conditions for EC2 to be created
        ec2objects = [
            {'KeyName': 'test_ec2_name_1'}
        ]
        #Create EC2
        for o in ec2objects:
            client.run_instances(
                ImageId='ami-03cf127a',
                MinCount=1,
                MaxCount=1,
                KeyName=o.get('KeyName'))

    @mock_ec2
    def test_case_1(self):
        #Run the app
        app.main()

    @mock_ec2
    def test_case_2(self):
        #Run the app
        app.main()


if __name__ == '__main__':
    unittest.main()

result.


test_case_1 (tests.test_setUp.MyTestCase) ... []
ok
test_case_2 (tests.test_setUp.MyTestCase) ... []
ok

----------------------------------------------------------------------
Ran 2 tests in 0.458s

OK

EC2 name is not output. The expiration date of the mock by moto seems to be until the end of the method, and if it is described in the setUp method, the mock will disappear at the end of the setUp method. As a result, the mock does not exist when the test case is executed.

3. Create a common class and execute it from each method

From the result of the previous section, I found that mock must be created without test cases, so I will create a common class and try to execute the methods in the common class from each case.

test.py


import unittest
import boto3
from moto import mock_ec2
from app import app


class common:
    @staticmethod
    def enviroment_1(name):
        client = boto3.client('ec2')
        #Set the conditions for EC2 to be created
        ec2objects = [
            {'KeyName': name}
        ]
        #Create EC2
        for o in ec2objects:
            client.run_instances(
                ImageId='ami-03cf127a',
                MinCount=1,
                MaxCount=1,
                KeyName=o.get('KeyName'))


class MyTestCase(unittest.TestCase):

    @mock_ec2
    def setUp(self):
        self.common = common

    @mock_ec2
    def test_case_1(self):
        #Create EC2
        self.common.enviroment_1('test_ec2_name_1')
        #Run the app
        app.main()

    @mock_ec2
    def test_case_2(self):
        #Create EC2
        self.common.enviroment_1('test_ec2_name_2')
        #Run the app
        app.main()


if __name__ == '__main__':
    unittest.main()

result.


test_case_1 (tests.test_common.MyTestCase) ... ['test_ec2_name_1']
ok
test_case_2 (tests.test_common.MyTestCase) ... ['test_ec2_name_2']
ok

----------------------------------------------------------------------
Ran 2 tests in 0.489s

OK

I was able to share it in a nice way, and the results I expected were returned. However, creating a common class increases the number of codes, so I want to make it a little easier.

4. Create a common method in the test class

In the first place, I finally realize that it is the quickest if I can create common methods other than test cases in the test class.

test.py


import unittest
import boto3
from moto import mock_ec2
from app import app


class MyTestCase(unittest.TestCase):
    @mock_ec2
    def test_cace_1(self):
        #Create EC2
        self.__common('test_ec2_name_1')
        #Run the app
        app.main()

    @mock_ec2
    def test_cace_2(self):
        #Create EC2
        self.__common('test_ec2_name_2')
        #Run the app
        app.main()

    def __common(self, name):
        client = boto3.client('ec2')
        #Set the conditions for EC2 to be created
        ec2objects = [
            {'KeyName': name}
        ]
        #Create EC2
        for o in ec2objects:
            client.run_instances(
                ImageId='ami-03cf127a',
                MinCount=1,
                MaxCount=1,
                KeyName=o.get('KeyName'))


if __name__ == '__main__':
    unittest.main()

result.


test_case_1 (tests.test.MyTestCase) ... ['test_ec2_name_1']
ok
test_case_2 (tests.test.MyTestCase) ... ['test_ec2_name_2']
ok

----------------------------------------------------------------------
Ran 2 tests in 0.361s

OK

did it. This is the smartest commonality that can be done now.

Recommended Posts

Common mock by moto in Python Unittest
Unittest in python
Unittest and CI in Python
Sort by date in python
[Python] Test sample using unittest2, mock
Python unittest module execution in vs2017
Read the file line by line in Python
Automate jobs by manipulating files in Python
Alignment algorithm by insertion method in Python
Scene recognition by GIST features in Python
Python in optimization
CURL in python
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
Meta-analysis in Python
Epoch in Python
Discord in Python
Sudoku in Python
DCI in Python
quicksort in python
nCr in python
N-Gram in Python
Programming in python
Plink in Python
Constant in python
Lifegame in Python.
FizzBuzz in Python
StepAIC in Python
N-gram in python
Csv in python
Disassemble in Python
Reflection in Python
Constant in python
nCr in Python.
format in python
Scons in Python3
Puyo Puyo in python
python in virtualenv
PPAP in Python
Quad-tree in Python
Reflection in Python
Chemistry in Python
Hashable in python
DirectLiNGAM in Python
Split camel case string word by word in Python
LiNGAM in Python
Flatten in python
flatten in python
Implemented in Python PRML Chapter 4 Classification by Perceptron Algorithm
How to run tests in bulk with Python unittest
[Maya Python] Display .ui created by Qt Designer in Maya
[Python] Get element by specifying name attribute in BeautifulSoup
How to run setUp only once in python unittest
Shift the alphabet string by N characters in Python
Store the stock price scraped by Python in the DB
gitwatch> python> Top 30 Python Projects In GitHub> OCT 19, 2014 BY DSK
Group by consecutive elements of a list in Python
Visualize long meetings in Python ~ Speaker identification by PyTorch ~
Daily AtCoder # 36 in Python
Clustering text in Python