Las pruebas automatizadas deben ser DDT controladas por datos

Introducción

  ¿Alguna vez te has sentido así? En el proceso de pruebas automatizadas, ya sean pruebas automatizadas de API o pruebas automatizadas de UI, una gran parte de nuestro tiempo escribiendo scripts de prueba es para preparar datos (configuración) y limpiar datos (tearDown). Porque los datos son una parte vital de las pruebas automatizadas. De esta manera, la información basada en datos es realmente importante. El siguiente contenido para compartir es: DDT, un marco basado en datos de uso común en el marco de prueba Unittest.

 

Impulsado por datos

1. ¿Qué se basa en datos?

  Basado en datos se refiere a la forma de procesar datos de prueba en pruebas automatizadas.

  Por lo general, los datos de prueba se separan de la función de función y se almacenan en una ubicación externa de la función de función . Cuando se está ejecutando la prueba automatizada, el marco basado en datos leerá los datos en la fuente de datos, pasará los datos como un parámetro a la función de función y ejecutará la misma función de función varias veces según la cantidad de datos .

  Las fuentes de datos basadas en datos pueden ser recopilaciones de datos fuera de funciones, archivos CSV, tablas de Excel, archivos TXT y bases de datos.

 

2. ¿Cuáles son las ventajas de la gestión de datos?

  (1) Reducir el código repetitivo
  A través de los siguientes ejemplos, veamos cómo los datos basados ​​en datos pueden reducir el código repetitivo.

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)

  Si no utiliza datos controlados y hay varios datos de prueba para la misma función, solo puede llamar a esta función varias veces; además, una vez que se modifican / eliminan ciertos datos de prueba, debe cambiar el correspondiente La prueba en la llamada de función Data es muy inconveniente.

  Si usa pruebas controladas, su código puede verse así:

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

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

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

  En este caso, no necesita realizar varias llamadas y, cuando cambian los datos de prueba, solo necesita cambiar los datos en el archivo de origen de datos.

 

  (2) El fallo del caso de prueba al que pertenecen los datos no afectará a los casos de prueba correspondientes a otros datos de prueba.
  A través de los siguientes ejemplos, veamos cómo los casos de prueba correspondientes a otros datos de prueba no se verán afectados.
  Si no utiliza datos controlados, suponga que existe una de las siguientes funciones:

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

test_001(test_data)

  

El resultado de la ejecución es como se muestra en la siguiente figura:
imagen

 

  Se puede ver en el resultado de la ejecución que debido a que el primer valor de test_data es 0, no es mayor que 0. Por lo tanto, la aserción falla y todos los datos de prueba después de 0 en el conjunto de datos de prueba test_data no se ejecutan.

  Si hay una unidad de datos, la unidad de datos descompondrá esta prueba en varias pruebas de acuerdo con los datos de la prueba, por lo que la falla de los primeros datos de prueba no afectará los resultados de la prueba posterior.

 

3. ¿Cuáles son los marcos basados ​​en datos más utilizados en Python?

  • DDT (pruebas basadas en datos), generalmente combinado con Unittest

  • parametrizado, un marco de uso común para Pytest para implementar datos basados ​​en

     

Qué decoradores están incluidos en DDT

Decorador de 1 clase

  El decorador de la clase ddt debe estar decorado en una subclase de TestCase. TestCase es una clase base en el marco de Unittest. Implementa la interfaz requerida por Test Runner para impulsar las operaciones de prueba.

 

2 métodos decoradores

  Ellos son: datos y file_data.
  El decorador de datos proporciona datos de prueba directamente; el
  decorador file_data carga datos de prueba de archivos JSON o YAML.

 

Los pasos para usar DDT son los siguientes:

  • Use @ddt para decorar su clase de prueba;

  • Utilice @data o @file_data para decorar los métodos de prueba que necesita basados ​​en datos;

  • Si un conjunto de datos de prueba tiene varios parámetros, necesita descomprimir, use @unpack para decorar su método de prueba.

     

Python instala DDT:

  Comando de instalación: pip install ddt o python -m pip install ddt

 

Uso de DDT

(1), ddt proporciona datos directamente

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)

  En este ejemplo, utilicé el decorador @data directamente. En este decorador, doy 2 conjuntos de datos para probar, a saber, ['Pruebas', 'Pruebas'] y ['hello_world.com', 'Pruebas']; luego uso el decorador @unpack para poner cada Los datos del grupo los datos se descomprimen como un parámetro y se pasan a mi función test_baidu_search.

  Cuando ejecute el código anterior, encontrará en los resultados que, aunque solo tenemos un caso de prueba test_baidu_search. Pero en el informe de prueba generado, se muestra "Ejecutar 2 pruebas en XX", es decir, test_baidu_search se ha ejecutado dos veces, esto significa que el DDT está funcionando.

  Este es el caso de múltiples conjuntos de parámetros y múltiples datos en cada grupo ¿Qué pasa si solo hay un dato en cada grupo? Solo necesita cambiar lo siguiente:

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

 

(2), ddt utiliza la función para proporcionar datos
  ddt proporciona datos directamente, excepto por lo mencionado anteriormente escribiendo directamente los datos en los parámetros de @data (), existe otra situación, es decir, los datos se obtienen primero del función, y luego se escribe en @data () en los parámetros.

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)

  En el ejemplo anterior, creé una función get_test_data () para obtener mis datos de prueba. Esta función puede tomar parámetros o no tomar parámetros, según la lógica de su negocio.

  Nota: El valor de retorno de get_test_data () debe cumplir con el formato de datos aceptable de ddt.data ().

      Es decir: un conjunto de datos, cada dato es un valor único; varios conjuntos de datos, cada grupo de datos es una lista o un diccionario.

 

(3) ddt usa archivos para proporcionar datos:
  además de usar @ddt para proporcionar datos directamente para JSON y YAML , DDT también admite la carga de datos a través de archivos.

  Sin embargo, solo se admiten dos formatos de forma predeterminada, YAML y JSON, solo los que terminan en ".yml" o ".yaml" se considerarán archivos YAML, y los demás formatos se considerarán archivos JSON.

  Si cambiamos el caso de uso anterior para usar archivos JSON, nuestro caso de uso se ve así:
imagen

  

     Primero, creamos un archivo test_baidu.json con el mismo nombre que test_baidu.py, el contenido es el siguiente:

{ "case1": {

  "search_string": "testing",

  "expect_string": "Testing"

  },

  "case2": {

  "search_string": "testing",

  "expect_string": "Testing"

  }

}

 

     Luego actualice test_baidu.py, el código actualizado es el siguiente:

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)

 

Como puede ver, usar el decorador @file_data es un poco diferente de usar el decorador @data:

  • En el decorador @file_data, la ruta del archivo es relativa a la propia clase de prueba. En este ejemplo, es la posición relativa del archivo donde se encuentra la clase de prueba Baidu;

  • El uso de @file_data no necesita usar unpack, incluso si hay varios parámetros para el mismo conjunto de datos.

     

Si usa el archivo YAML en el ejemplo anterior, debe prestar atención a los siguientes puntos:

  • Si desea utilizar archivos yaml en python, debe instalar PyYAML.

  • Comando de instalación: pip install pyyaml ​​o python -m pip install pyyaml

     

Después de la instalación, creamos un archivo test_baidu.yaml en el mismo directorio de test_baidu.json con el siguiente contenido:

"case1":

  "search_string": "testing"

  "expect_string": "Testing"

"case2": 

  "search_string": "testing"

  "expect_string": "Testing"

Luego, cambiamos test_baidu.py, el contenido cambiado es el siguiente:

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)

  Como puede ver, a diferencia del uso de archivos JSON, PyYaml debe instalarse primero para usar archivos YAML. Luego, para evitar fallas en la importación de yaml, definí el decorador need_yaml para agregar un juicio de seguridad a mi programa.

      Si la importación falla, no se ejecutarán todos los casos de prueba decorados con need_yaml.

 

(4) ddt utiliza archivos para proporcionar datos: otros archivos de datos de formato
  porque ddt solo admite datos en formato JSON y YAML de forma predeterminada. Pero, ¿y si quiero utilizar otros formatos de datos?

  Hay dos métodos de uso común como sigue:

  • Primero lea archivos en otros formatos (como formato Excel), luego cree un archivo JSON o YAML compatible con ddt, y finalmente escriba los datos obtenidos en este archivo, y luego use @file_data ();

  • Cree una función, lea archivos en otros formatos y obtenga datos en la función, y devuelva los datos directamente al formato admitido por @ ddt.data ().

 

Bienvenido a prestar atención a la cuenta pública de [The Way of Infinite Testing], responder a [recibir recursos],
recursos de aprendizaje de programación de Python productos secos, automatización de la interfaz de usuario de la aplicación del marco Python + Appium , automatización de la interfaz de usuario web del marco Python + Selenium, API del marco Python + Unittest automatización,


Los recursos y códigos se envían gratis ~
Hay un código QR de la cuenta oficial en la parte inferior del artículo, puede escanearlo en WeChat y seguirlo.

Observaciones: Mi cuenta pública personal se ha abierto oficialmente, dedicada al intercambio de tecnología de prueba, que incluye: pruebas de big data, pruebas funcionales, desarrollo de pruebas, automatización de la interfaz API, operación y mantenimiento de pruebas, pruebas de automatización de la interfaz de usuario, etc., búsqueda pública de WeChat cuenta: "Wuliang The Way of Testing", o escanee el código QR a continuación:

 ¡Presta atención y crezcamos juntos!

Supongo que te gusta

Origin blog.csdn.net/weixin_41754309/article/details/113093496
Recomendado
Clasificación