Pandas y Excel implementan la unidad de datos Pytest

Introducción

La prueba automatizada de los tweets compartidos anteriormente debe ser basada en datos. DDT   introdujo la operación de archivos JSON y YAML en el marco de prueba de  unidad para lograr resultados basados ​​en datos. Entonces, en pytest, ¿cómo debería implementarse?

 

Pytest manipula archivos JSON / YAML para lograr datos controlados

Primero, cree un método para leer archivos JSON y archivos YAML de acuerdo con la idea básica de usar pytest para datos controlados:

def test_read_data_from_json_yaml(data_file):

    return_value = []

    data_file_path = os.path.abspath(data_file)

    print(data_file_path)

    _is_yaml_file = data_file_path.endswith((".yml", ".yaml"))

    with codecs.open(data_file_path, 'r', 'utf-8') as f:

        #从YAML或JSON文件中加载数据

        if _is_yaml_file:

            data = yaml.safe_load(f)

        else:

            data = json.load(f)

    for i, elem in enumerate(data):

        if isinstance(data, dict):

            key, value = elem, data[elem]

            if isinstance(value, dict):

                case_data = []

                for v in value.values():

                    case_data.append(v)

                return_value.append(tuple(case_data))

            else:

                return_value.append((value,))

    return return_value

La función test_read_data_from_json_yaml realiza la lectura automática de archivos JSON y archivos YAML, y extrae los datos en los archivos JSON y YAML, y los devuelve de una manera que puede ser recibida por pytest.mark.parametrize.

 

Con este método de función, los datos del archivo JSON o YAML se pueden convertir al formato reconocido por pytest.mark.parametrize y pasar directamente a través de este método.

 

Practiquemos y creemos los siguientes directorios de archivos en el directorio raíz del proyecto APITest:

|--APITest

    |--tests_pytest_ddt

        |--test_baidu_ddt.py

        |--test_baidu_ddt.json

        |--test_baidu_ddt.yaml

        |--test_baidu_ddt.xlsx

        |--__init__.py

        |--conftest.py

Entre ellos, el contenido del archivo test_baidu_ddt.json es el siguiente:

{ 

  "case1": {

  "search_string": "testing",

  "expect_string": "Testing"

  },

  "case2": {

  "search_string": "hello_world.com",

  "expect_string": "Testing"

  }

}

El contenido del archivo test_baidu_ddt.yaml es el siguiente:

"case1":

  "search_string": "testing"

  "expect_string": "Testing"

"case2": 

  "search_string": "hello_world.com"

  "expect_string": "Testing"

El código del archivo test_baidu_ddt.py es el siguiente:

import codecs
import json
import os
import time
import pytest
import yaml


def test_read_data_from_json_yaml(data_file):

    return_value = []

    data_file_path = os.path.abspath(data_file)

    print(data_file_path)

    _is_yaml_file = data_file_path.endswith((".yml", ".yaml"))

    with codecs.open(data_file_path, 'r', 'utf-8') as f:

        #从YAML或JSON文件中加载数据

        if _is_yaml_file:

            data = yaml.safe_load(f)

        else:

            data = json.load(f)

    for i, elem in enumerate(data):

        if isinstance(data, dict):

            key, value = elem, data[elem]

            if isinstance(value, dict):

                case_data = []

                for v in value.values():

                    case_data.append(v)

                return_value.append(tuple(case_data))

            else:

                return_value.append((value,))

    return return_value


@pytest.mark.baidu
class TestBaidu:

    @pytest.mark.parametrize('search_string, expect_string',  test_read_data_from_json_yaml('tests_pytest_ddt/test_baidu_ddt.yaml'))

    def test_baidu_search(self, login, search_string, expect_string):

        driver, s, base_url = login

        driver.get(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)

        assert (expect_string in search_results) is True



if __name__ == "__main__":

    pytest.main(['-s', '-v'])

El código en este archivo es   casi el mismo que el código explicado en el marco de prueba Pytest-Data Drive . El único cambio es que se ha agregado un nuevo método test_read_data_from_json_yaml. Además, los parámetros de @ pytest.mark.parametrize han cambiado de Proporcionar directamente parámetros a los archivos. Proporcionar parámetros.

(test_read_data_from_json_yaml('tests_pytest_ddt/test_baidu_ddt.yaml'))

 

Ejecútelo en la línea de comando de la siguiente manera:

D:\Python_Test\APITest>pytest tests_pytest_ddt -s -v

 

Después de la ejecución, los resultados son los siguientes:
imagenSe
puede ver que ambos casos de prueba se han ejecutado y los datos del archivo YAML se han leído correctamente.

Entonces, ¿qué pasa si queremos ejecutar los datos en el archivo JSON ahora? Reemplace el sufijo del archivo yaml pasado en el código anterior con el sufijo del archivo json y ejecútelo nuevamente.

 

Pytest manipula archivos de Excel para lograr una unidad de datos

En aplicaciones prácticas, muchas empresas también utilizan Excel para la conducción de datos. En Python, hay muchas bibliotecas para leer y escribir Excel, las más comunes son xlrd, xlwt y openpyxl. Dado que xlrd y xlwt solo se pueden usar para leer y escribir, respectivamente, para lograr las mismas operaciones de lectura y escritura, tiene una gran cantidad de líneas de código, por lo que gradualmente se ha vuelto menos popular. Entonces, lo siguiente se centrará en el uso de openpyxl.

 

instalación openpyxl

pip install openpyxl

 

uso de openpyxl

from openpyxl import load_workbook, Workbook

if __name__ == "__main__":
    # 创建一个workbook
    file_name = r'c:\test.xlsx'
    wb = Workbook()

    # 创建一个sheet,名为Testing,把它插入到最前的位置
    wb.create_sheet('Testing',0)

    # 创建一个sheet,名为TEST,把它插入index为1的位置
    wb.create_sheet('TEST',1)

    # 保存表格
    wb.save(file_name)
    
    # 读和写
    # 初始化表格
    wb2 = load_workbook(file_name)

    # 读,获取所有的sheet名称
    print(wb2.sheetnames)


    # 获取sheet名为Testing的表格
    s = wb2['Testing']

    # 将A1行的值设置为Testing
    s['A1'] = 'Testing'

    # 将第2行,第一列的值设置为1
    s.cell(row=2, column=1).value = 1

    # 打印第2行第一列单元格的值 --方法1
    print(s.cell(row=2,column=1).value)

    # 打印第2行第一列单元格的值 --方法2
    print(s['A2'].value)

    # 保存表格
    wb.save(file_name)

Como se muestra en el bloque de código anterior, presenta brevemente el uso de openpyxl, que implica crear una tabla, crear un nombre de hoja, leer el valor de una celda, establecer el valor de una celda, etc. Puede ver que usar openpyxl para operar Excel es relativamente simple.

 

openpyxl combinado con pytest para lograr datos basados ​​en

El contenido del archivo test_baidu_ddt.xlsx es el siguiente (nombre de la hoja Prueba):
imagen
Escribamos un método para leer Excel, el código es el siguiente:

def test_read_data_from_excel(excel_file, sheet_name):

    return_value = []

    # 判断文件是否存在
    if not os.path.exists(excel_file):
        raise ValueError("File not exists")

    # 打开指定的sheet
    wb = load_workbook(excel_file)

    # 按照pytest接受的格式输出数据
    for s in wb.sheetnames:
        if s == sheet_name:
            sheet = wb[sheet_name]
            for row in sheet.rows:
                return_value.append([col.value for col in row])

    # 第一行数据是标题,故skip掉
    return return_value[1:]

Actualice el archivo test_baidu_ddt.py y agregue el método test_read_data_from_excel. El código actualizado es el siguiente:

import codecs
import json
import os
import time
import pytest
import yaml
from openpyxl import load_workbook


def test_read_data_from_json_yaml(data_file):
    return_value = []
    data_file_path = os.path.abspath(data_file)
    print(data_file_path)

    _is_yaml_file = data_file_path.endswith((".yml", ".yaml"))
    with codecs.open(data_file_path, 'r', 'utf-8') as f:
        # 从YAML或JSON文件中加载数据
        if _is_yaml_file:
            data = yaml.safe_load(f)
        else:
            data = json.load(f)

    for i, elem in enumerate(data):
        if isinstance(data, dict):
            key, value = elem, data[elem]
            if isinstance(value, dict):
                case_data = []
                for v in value.values():
                    case_data.append(v)
                return_value.append(tuple(case_data))
            else:
                return_value.append((value,))
    return return_value


def test_read_data_from_excel(excel_file, sheet_name):

    return_value = []
    if not os.path.exists(excel_file):
        raise ValueError("File not exists")

    wb = load_workbook(excel_file)
    for s in wb.sheetnames:
        if s == sheet_name:
            sheet = wb[sheet_name]
            for row in sheet.rows:
                return_value.append([col.value for col in row])
    print(return_value)
    return return_value[1:]


@pytest.mark.baidu
class TestBaidu:
    # 注意,此处调用我换成了读Excel的方法

    @pytest.mark.parametrize('search_string, expect_string',  test_read_data_from_excel(r'D\Python_Test\APITest\tests_pytest_ddt\test_baidu_ddt.xlsx', 'Testing'))

    def test_baidu_search(self, login, search_string, expect_string):
        driver, s, base_url = login
        driver.get(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)
        assert (expect_string in search_results) is True


if __name__ == "__main__":
    pytest.main(['-s', '-v','tests_pytest_ddt'])

Ejecútelo de nuevo en la línea de comando de la siguiente manera:

D:\Python_Test\APITest>pytest tests_pytest_ddt -s -v

Verifique los resultados después de la ejecución, encontrará que la prueba se ejecuta correctamente y los datos de la prueba se obtienen del nombre de hoja especificado por Excel.

 

 

Pandas se basa en datos

Openpyxl opera Excel de manera muy concisa, pero en comparación con Pandas, no es lo suficientemente conciso y openpyxl no es tan eficiente como Pandas, especialmente cuando hay demasiadas líneas de línea de tabla, openpyxl es más lento.

Pandas es un poderoso conjunto de herramientas para analizar datos estructurados. Se basa en Numpy (que proporciona operaciones matriciales de alto rendimiento), Pandas se utiliza para la minería de datos y el análisis de datos, y también proporciona funciones de limpieza de datos. Usar Pandas para manipular datos de Excel será muy simple.

 

Instalación de pandas

# pandas默认依赖xlrd库,故先安装xlrd
pip install xlrd

# 安装Pandas
pip install Pandas

 

Sintaxis de pandas

import Pandas as pd

# 首先初始化,engine默认是xlrd
s = pd.ExcelFile(path_or_buffer, engine=None)



# 接着parse
s.parse(sheet_name=0,header=0,names=None,index_col=None,usecols=None,

squeeze=False,converters=None,true_values=None,false_values=None,

skiprows=None,nrows=None,na_values=None,parse_dates=False,

date_parser=None,thousands=None,comment=None,skipfooter=0,

convert_float=True,mangle_dupe_cols=True,**kwds,)

Pandas lee archivos de Excel muy fácilmente, primero use Pandas para inicializar ExcelFile. Los dos parámetros path_or_buffer son la ruta del archivo que queremos leer.

Se recomienda utilizar la ruta en inglés y el método de nomenclatura en inglés para el nombre del archivo de Excel, no en chino.

import pandas as pd

path_or_buffer = r'D:\Python_Test\APITest\tests_pytest_ddt\test_baidu_ddt.xlsx'

engine es el motor utilizado por Pandas. Las opciones disponibles son "xlrd", "openpyxl", "odf" y "pyxlsb". Si no se proporciona, xlrd se utiliza de forma predeterminada.

 


Una vez inicializados los parámetros de la función parse , se puede utilizar la función s.parse (). La función de análisis tiene muchos parámetros, y aquí solo se enumeran unos pocos de uso común.

 

sheet_name: el nombre de la hoja de Excel
sheet_name puede ser un número entero, un nombre de lista o una combinación de los dos.

# 通过整型数字读取。读取第一个sheet。Pandas sheet名下标以0开始
s = pd.ExcelFile(path_or_buffer, sheet_name = 0)

# 通过列表名读取
data = s.parse(sheet_name = 'Testing')

# 通过index读取。读取第一个sheet
data = s.parse(sheet_name = 0)

#组合读取。读取第4个sheet,名为Testing的sheet以及第7个sheet
data = s.parse(sheet_name = [3, 'Testing', 'Sheet6'])

 

encabezado: qué fila usar como nombre de columna. El
valor predeterminado del encabezado es 0, que es la primera fila. También se puede establecer en [0, x].
(Por ejemplo, [0,1] significa usar las dos primeras filas como índices múltiples)

data = s.parse(sheet_name = 'Testing', header = 0)

Nota: Pandas usa la primera fila de encabezados de forma predeterminada, por lo que en Excel, la primera fila debe ser título. Si la primera fila son datos, se omitirá la primera fila de datos. Si no desea el encabezado, puede pasar header = None como parámetro.

 

usecols: la columna que se debe leer
usecols recibe un número entero, comenzando desde 0, como [0, 1, 2], o nombres de columna como "A: D, F", que significa leer las columnas A a D, y column F.

data = s.parse(sheet_name = 'Testing', usecols='A:D')

 

skiprows: al leer, omitir filas específicas
skiprows = n, omitir las primeras n filas; omitir filas = [a, b, c], omitir filas a + 1, b + 1, c + 1 (el índice comienza desde 0)

data = s.parse(sheet_name = 'iTesting', skiprows = [1,2,3])

 

nrows: el número de filas
que se leerán, solo el número de filas que se leerán

data = s.parse(sheet_name = 'Testing', nrows = 3)

 

Pandas combinado con Pytest para lograr datos basados ​​en

Después de comprender la sintaxis de Pandas, echemos un vistazo a cómo usar Pandas para leer datos de Excel:

def test_read_data_from_pandas(excel_file, sheet_name):

    if not os.path.exists(excel_file):
        raise ValueError("File not exists")

    # 初始化
    s = pd.ExcelFile(excel_file)

    # 解析Excel Sheet
    df = s.parse(sheet_name)

    # 以list格式返回数据
    return df.values.tolist()

Como puede ver, usar pandas para leer datos de Excel es más conciso y conveniente.
Finalmente, actualice el archivo test_baidu_ddt.py, el código actualizado es el siguiente:

import codecs
import json
import os
import time
import pytest
import yaml
from openpyxl import load_workbook
import pandas as pd

# 读取Yaml文件和Json文件
def test_read_data_from_json_yaml(data_file):
    return_value = []
    data_file_path = os.path.abspath(data_file)
    print(data_file_path)

    _is_yaml_file = data_file_path.endswith((".yml", ".yaml"))
    with codecs.open(data_file_path, 'r', 'utf-8') as f:
        #从YAML或JSON文件中加载数据
        if _is_yaml_file:
            data = yaml.safe_load(f)
        else:
            data = json.load(f)

    for i, elem in enumerate(data):
        if isinstance(data, dict):
            key, value = elem, data[elem]
            if isinstance(value, dict):
                case_data = []
                for v in value.values():
                    case_data.append(v)
                return_value.append(tuple(case_data))
            else:
                return_value.append((value,))
    return return_value

# 读取Excel 文件 -- openpyxl
def test_read_data_from_excel(excel_file, sheet_name):
    return_value = []

    if not os.path.exists(excel_file):
        raise ValueError("File not exists")

    wb = load_workbook(excel_file)
    for s in wb.sheetnames:
        if s == sheet_name:
            sheet = wb[sheet_name]
            for row in sheet.rows:
                return_value.append([col.value for col in row])
    print(return_value)
    return return_value[1:]

# 读取Excel文件 -- Pandas
def test_read_data_from_pandas(excel_file, sheet_name):
    if not os.path.exists(excel_file):
        raise ValueError("File not exists")
    s = pd.ExcelFile(excel_file)
    df = s.parse(sheet_name)
    return df.values.tolist()

@pytest.mark.baidu
class TestBaidu:

    @pytest.mark.parametrize('search_string, expect_string',  test_read_data_from_pandas(r'D:\Python_Test\APITest\tests_pytest_ddt\test_baidu_ddt.xlsx', 'Testing'))
    def test_baidu_search(self, login, search_string, expect_string):
        driver, s, base_url = login
        driver.get(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)
        assert (expect_string in search_results) is True


if __name__ == "__main__":
    pytest.main(['-s', '-v', 'tests_pytest_ddt'])

Ejecútelo de nuevo en la línea de comando de la siguiente manera:

D:\Python_Test\APITest>pytest tests_pytest_ddt -s -v

Verifique los resultados después de la ejecución, puede encontrar que la prueba se ejecuta correctamente y los datos de la prueba se obtienen del nombre de la hoja especificada por Excel a través de Pandas.


De hecho, Pandas puede leer no solo archivos de Excel, sino también archivos HTML, archivos TXT, archivos JSON, archivos de base de datos (.sql), etc. En el campo del análisis de datos, Pandas se usa ampliamente. Para un uso más específico de Pandas, consúltelo usted mismo.

Bienvenido a prestar atención a la cuenta pública de [The Way of Infinite Testing], responder [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 , automatización de la API del marco Python + Unittest,


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/113662924
Recomendado
Clasificación