Tests de code dans le temps en Python

1.Tout d'abord

Si le test de temps est effectué manuellement, il peut être ennuyeux de changer le sysdate, et des bogues sont susceptibles d'être mélangés. J'ai donc codé le test et l'ai exécuté plus facilement pour voir s'il pouvait améliorer la qualité.

2. Environnement d'exécution, outils

L'environnement d'exécution est le suivant

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.1
BuildVersion:	19B88

$ python --version
Python 3.7.4

Essayez également d'utiliser un package appelé freezegun pour tester facilement à tout moment. Vous pouvez utiliser ce paquet appelé freezegun pour remplacer l'heure actuelle obtenue à partir de datetime dans la bibliothèque standard de Python par celle spécifiée.

3. Utilisez freezegun

Lorsque je teste le traitement dans le temps, bien sûr, je veux tester à plusieurs reprises. Cependant, exécuter le test tout en modifiant l'heure du système juste pour cela est ennuyeux. Donc, si vous utilisez freezegun, vous n'aurez pas à faire cela. Installez le package à partir de la commande pip.

$ pip install freezegun

4. Essayez de revenir à une heure précise

Dans freezegun,freezegun.freeze_time ()peut être remplacé pour que la fonction du module datetime renvoie une heure spécifique. L'exemple de code examine le contenu de datetime.now ().

app_freezegun.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import freezegun
from datetime import datetime


def main():
    #Remplacez et affichez l'heure actuelle à l'aide du freezegun
    freezer = freezegun.freeze_time('2015-10-21')
    freezer.start()
    try:
        print("freezegun:" + str(datetime.now()))
    finally:
        freezer.stop()
    
    #Afficher l'heure actuelle
    print("nowtime:" + str(datetime.now()))


if __name__ == '__main__':
    main()

Faites ce qui précède.

$ python app_freezegun.py
freezegun:2015-10-21 00:00:00
nowtime:2019-12-14 10:16:49.847317

Vous pouvez voir que l'heure actuelle a été remplacée lors de l'utilisation du freezegun.

5. Utiliser comme décorateur

Ensuite, un modèle qui utilise l'API comme décorateur. L'heure n'est remplacée que dans la fonction modifiée par le décorateur.

app_freezegun.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import freezegun
from datetime import datetime

#Remplacez et affichez l'heure actuelle à l'aide du freezegun
@freezegun.freeze_time('2015-10-21')
def main():
    print("freezegun:" + str(datetime.now()))

#Afficher l'heure actuelle
def main_2():
    print("nowtime:" + str(datetime.now()))


if __name__ == '__main__':
    main()
    main_2()

Faites ce qui précède.

$ python app_freezegun.py
freezegun:2015-10-21 00:00:00
nowtime:2019-12-14 10:16:49.847317

Vous pouvez voir que l'heure actuelle dans la fonction qualifiée de décorateur a été remplacée. Bien sûr, vous pouvez également spécifier l'heure.

app_freezegun.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import freezegun
from datetime import datetime

#Remplacer l'heure actuelle à l'aide de Freeze
@freezegun.freeze_time('2015-10-21 12:34:56')
def main():
    print("freezegun:" + str(datetime.now()))


if __name__ == '__main__':
    main()

Le résultat est le suivant.

$ python app_freezegun.py 
freezegun:2015-10-21 12:34:56

6. Utiliser comme gestionnaire de contexte

Plus tôt, j'ai spécifié l'heure à l'aide d'un décorateur. La même API peut également être utilisée comme gestionnaire de contexte. Voici le modèle utilisé comme gestionnaire de contexte. Dans ce cas, l'heure n'est remplacée que dans le bloc du gestionnaire de contexte.

app_freezegun.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import freezegun
from datetime import datetime


def main():
    #Remplacez et affichez l'heure actuelle à l'aide du freezegun
    with freezegun.freeze_time('2015-10-21'):
        print("freezegun:" + str(datetime.now()))

    #Afficher l'heure actuelle
    print("nowtime:" + str(datetime.now()))


if __name__ == '__main__':
    main()

Le résultat est le même que [4.], il est donc omis.

7. Décaler l'heure d'une heure précise

Lors d'un test, je pense qu'il est nécessaire de définir une fois l'heure standard, puis de décaler l'heure après avoir effectué un processus spécifique. Essayez d'utiliser freezegun.

Dans l'exemple de code suivant, tick () est utilisé pour décaler l'heure par l'objet timedelta etmove_to ()est utilisé pour changer l'heure.

app_freezegun.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import freezegun
from datetime import datetime
from datetime import timedelta


def main():
    with freezegun.freeze_time('2015-10-21 00:00:00') as freeze_datetime:
        print(datetime.now())

        #Avancez le temps de 1 seconde
        freeze_datetime.tick()
        print(datetime.now())

        #Avancez l'heure de 1 minute
        freeze_datetime.tick(delta=timedelta(minutes=1))
        print(datetime.now())

        #Passer à une heure précise
        freeze_datetime.move_to('2019-01-01 00:00:00')
        print(datetime.now())


if __name__ == '__main__':
    main()

Faites ce qui précède.

$ python app_freezegun.py 
2015-10-21 00:00:00
2015-10-21 00:00:01
2015-10-21 00:01:01
2019-01-01 00:00:00

8. Essayez de l'incorporer dans le test unitaire

J'ai vérifié diverses choses, mais voici la production réelle. Utilisez freezegun dans ʻunit test. Je veux tester ce qui est créé automatiquement à l'aide de datetime`, alors moquez-vous d'AWS EC2. Tout d'abord, préparez l'application. Obtenez l'EC2 créé, récupérez celui qui est plus ancien que la date et l'heure d'exécution de l'application et renvoyez le nom de l'instance.

app_freezegun.py



#!/usr/bin/env python
# -*- coding: utf-8 -*-
import boto3
from datetime import datetime, timedelta, timezone


def main():
    #Obtenez l'heure actuelle
    now = datetime.now(timezone.utc)
    #Initialiser le nom de l'instance avec le tableau
    instace_names = []

    client = boto3.client('ec2')

    #Obtenez toutes les informations sur l'instance.
    instances = client.describe_instances()

    #Obtenez les instances créées avant la date d'exécution.
    for instance_list in instances.get('Reservations'):
        for instance in instance_list.get('Instances'):
            if now > instance.get('LaunchTime'):

                #Extrayez le nom de l'instance.
                instace_names.append(instance.get('KeyName'))

    return instace_names

Vient ensuite le code de test. Utilisez freezegun pour simuler 4 EC2 avec des dates de création différentes.

test_freezegun.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest
import boto3
from moto import mock_ec2
import freezegun
from datetime import datetime, timedelta
from app import app_freezegun as app


class MyTestCase(unittest.TestCase):
    @mock_ec2
    def test_case_1(self):
        with freezegun.freeze_time('2017-01-01 00:00:00') as freeze_datetime:
            #Date de création 2017-01-Créer EC2 avec 01
            self.__common('test_ec2_name_1')

            freeze_datetime.move_to('2018-01-01 00:00:00')
            #Date de création 2018-01-Créer EC2 avec 01
            self.__common('test_ec2_name_2')

            freeze_datetime.move_to('2019-01-01 00:00:00')
            #Date de création 2019-01-Créer EC2 avec 01
            self.__common('test_ec2_name_3')

            freeze_datetime.move_to('2020-01-01 00:00:00')
            #Date de création 2020-01-Créer EC2 avec 01
            self.__common('test_ec2_name_4')

        #Exécutez l'application
        instance_names = app.main()

        #Vérifiez le résultat
        self.assertEqual(instance_names, ['test_ec2_name_1', 'test_ec2_name_2', 'test_ec2_name_3'])

    def __common(self, name):
        client = boto3.client('ec2')
        #Définir les conditions de création d'EC2
        ec2objects = [
            {'KeyName': name}
        ]
        #Créer EC2
        for o in ec2objects:
            client.run_instances(
                ImageId='ami-03cf127a',
                MinCount=1,
                MaxCount=1,
                KeyName=o.get('KeyName'))


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

Essayez de l'exécuter.

$ python -m unittest tests.test_freezegun -v
test_case_1 (tests.test_freezegun.MyTestCase) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.387s

OK

J'ai bien fait.

Recommended Posts

Tests de code dans le temps en Python
Générer du code QR en Python
Code de caractère appris en Python
[Python] Générer un code QR en mémoire
Formater automatiquement le code Python avec Vim
Mesurer le temps d'exécution de la fonction en Python
Ecrire le code de test du sélénium en python
Ecrire un test unitaire de langage C en Python
Code de vérification de la série Fourier écrit en Python
Il suffit d'imprimer le temps écoulé en Python en secondes
Obtenir la liste de codes EDINET en Python
Comparaison temporelle: calcul du coefficient de corrélation en Python
Quadtree en Python --2
Python en optimisation
CURL en Python
Métaprogrammation avec Python
Premier Python
Python 3.3 avec Anaconda
Géocodage en python
SendKeys en Python
Méta-analyse en Python
Unittest en Python
Époque en Python
mesure du temps python
Allemand en Python
DCI en Python
code de caractère python
tri rapide en python
nCr en python
N-Gram en Python
Programmation avec Python
Premier Python
Plink en Python
Constante en Python
FizzBuzz en Python
[Python] Code conscient des algorithmes
Sqlite en Python
Étape AIC en Python
LINE-Bot [0] en Python
CSV en Python
Assemblage inversé avec Python
Réflexion en Python
Constante en Python
nCr en Python.
format en python
PPAP en Python
Quad-tree en Python
Test unitaire Python
Réflexion en Python
Chimie avec Python
Hashable en Python
DirectLiNGAM en Python
LiNGAM en Python
Aplatir en Python
Aplatir en python
Obtenez des données de séries chronologiques de k-db.com avec Python
Heure à laquelle le terminal disparaît dans Visual Studio Code
Notes personnelles sur le code doc Python dans Sphinx