Python para o testador: como pequenos scripts c pandas ajudam a testar grandes conjuntos de dados

Trabalho como testador em um projeto, cuja essência é a coleta e armazenamento de vários dados e a formação de vários relatórios e upload de arquivos com base. Ao gerar esses relatórios, um grande número de condições para a seleção de dados é levado em consideração e, portanto, ao testar, você precisa trabalhar muito com as consultas SQL no banco de dados. Mas, para verificar a seleção correta de dados e procurar dados em excesso / ausentes, isso muitas vezes não é suficiente, então tive que procurar ferramentas adicionais para isso.

Como eu já tinha algum conhecimento básico de python, decidi tentar escrever pequenos scripts que me permitissem fazer algo com os dados existentes e, assim, facilitar e acelerar o processo de teste. Neste artigo, vou lhe contar o que aconteceu.

Projetando um Script Script


Para escrever um script, você precisa descobrir o que exatamente o script deve fazer, quais dados precisam ser inseridos e quais dados devem ser gerados.

Etapas de amostra para o cenário:

  1. Obtemos um arquivo com dados em um determinado formato (ou vários arquivos)
  2. Obter dados de arquivo / arquivos
  3. Selecionamos os dados necessários
  4. Realizamos algumas operações em dados
  5. Carregamos dados em um arquivo do Excel, se necessário (geralmente esse formato é o mais conveniente para análises e armazenamento adicionais)

Então você precisa pensar em como e onde obter informações. Este pode ser um arquivo criado manualmente com dados, fazendo o upload de dados para uma interface do usuário em um arquivo levando em consideração os filtros, um arquivo com análise de dados usando outro script, um arquivo para fazer upload dos resultados de uma consulta SQL no banco de dados (você pode fazer upload rápido de dados para um arquivo csv no banco de dados), json -file ou xml-file com dados da resposta a uma solicitação à API, etc.

Escrevemos scripts em python usando pandas e outras bibliotecas


Para escrever scripts em python, você precisa instalar um interpretador e um IDE adequado. Também é melhor criar um ambiente virtual separado para este projeto.

Eu uso bibliotecas diferentes para scripts, algumas delas são bibliotecas python internas , outras precisam ser instaladas adicionalmente:

  • pandas é uma biblioteca para análise de dados. Ele permite trabalhar com dados de arquivos de vários formatos, além de receber dados diretamente do banco de dados usando uma consulta SQL. Os dados dos arquivos são carregados nos quadros de dados (visualmente as mesmas tabelas do Excel), com dados nos quais você já pode executar operações diferentes: combine dados de diferentes quadros de dados por analogia com junção / união no SQL, selecione os dados necessários sob certas condições, compare os dados em diferentes colunas do quadro de dados etc.
  • openpyxl, xlrd - bibliotecas para trabalhar com o Excel.

A estrutura de script mais simples para trabalhar com dados de arquivos csv, json, Excel é a seguinte:

#   pandas
import pandas as pd

#    csv-  -
# (        )
#       csv-     ";"
df = pd.read_csv('./csv_file.csv', sep=';', encoding='utf-8')

# 
#    json-  -
# (        )
# df = pd.read_json('./json_file.json', encoding='utf-8')

# 
#    Excel-  -,     
# (        )
# file_excel = 'Excel_file.xlsx'
# df = pd.ExcelFile(file_excel).parse('1')


#  -     -  
#    - final_df


#    Excel-,  
#          
# (      )
writer = pd.ExcelWriter('.xlsx')
final_df.to_excel(writer, '1')
writer.save()

Nesse script, os dados de um arquivo com o formato requerido são carregados em um quadro de dados, os dados necessários são selecionados e algumas operações são executadas neles, e os dados são gravados em um novo arquivo do Excel.

Se você precisar trabalhar com dados obtidos como resultado de uma consulta SQL para o banco de dados, não poderá exportá-los para um arquivo csv, mas inseri-los imediatamente em um quadro de dados executando uma consulta SQL no banco de dados no próprio script:

#   pandas
import pandas as pd
#      ,     PostgreSQL
# (   -    )
import psycopg2

#    
conn = psycopg2.connect(dbname='_', host='', port='',
                        user='', password='')

#   SQL-
q = """select ... 
    from ... 
    where ..."""

#    -,  SQL-
df = pd.read_sql_query(q, conn)


#  -     -  
#    - final_df


#    Excel-,  
#          
# (      )
writer = pd.ExcelWriter('.xlsx')
final_df.to_excel(writer, '1')
writer.save()

Se você precisar obter dados de um arquivo xml, poderá usar as bibliotecas projetadas para isso. Eu uso a biblioteca interna ElementTree .

Quando os dados são recebidos em um quadro de dados, você pode combiná-los imediatamente com dados de outro quadro de dados (análogos de união ou união no SQL) ou executar algumas operações neles, por exemplo, remover duplicatas, remover linhas com valores vazios em determinadas células , compare dados em várias colunas, selecione as linhas / colunas desejadas etc. Leia mais na documentação para pandas.

Opções de uso de script


E agora ativamos a ferramenta principal do testador e selecionamos os dados / recursos em nosso projeto, para verificação de quais scripts seriam úteis.

Arquivos com uma pequena quantidade de dados de teste gerados usando dados gerados foram criados para os scripts . Na realidade, os arquivos de dados contêm dezenas de milhares de linhas e um grande número de colunas.

Cenário # 1

Existem três arquivos no formato csv com dados. Para cada linha de dados, há um campo com um ID de identificador exclusivo. Os dados desses arquivos são selecionados levando em consideração determinadas condições e inseridos em uma tabela no banco de dados; esses dados são exibidos em um relatório na forma de uma tabela na interface do usuário. É possível fazer upload de dados em uma interface do usuário para um arquivo do Excel.

Suponha que as condições para selecionar dados para um relatório a partir dos arquivos de origem sejam as seguintes:

  • Os arquivos podem ter duplicatas por ID; em um relatório, um registro com o mesmo identificador deve ser levado em consideração apenas uma vez (nesse caso, simplesmente selecionamos qualquer uma das linhas com esse identificador nos dados).
  • Linhas com dados ausentes na célula da coluna reg_date não devem ser contadas.
  • De fato, pode haver mais condições de seleção, os dados também podem ser comparados com os dados já existentes no sistema e apenas os dados de interseção por ID serão exibidos no relatório, mas, por exemplo, levaremos em conta apenas as duas condições indicadas acima.

A tarefa do testador: Verifique se as linhas com os objetos necessários estão corretamente selecionadas nos arquivos de origem e se todos esses objetos são exibidos no relatório na interface do usuário.

Nós compomos um script para o script:

  • - csv-, - ( union SQL), id, reg_date.
  • UI Excel-, , -.
  • (merge) - ( outer join SQL) Excel- .
  • , , - , , UI.

No arquivo final, os dados conterão apenas uma coluna com id, se os nomes das colunas em diferentes quadros de dados coincidirem e não for claro quais colunas / linhas de qual arquivo foram. Portanto, nomeio as colunas com um identificador exclusivo por nomes diferentes nos arquivos ou adiciono uma coluna separada “Linhas de um arquivo de tal e tal” a cada arquivo e coloco “Sim” nele - então, ao analisar o arquivo Excel resultante, é conveniente filtrar por esta coluna Porque eles sempre contêm um valor e, filtrando por eles, você já pode entender quais dados divergem nas colunas correspondentes.

Dados de exemplo do arquivo example1_csv_1.csv :



Dados de exemplo do arquivo report_UI.xlsx : Um



script python se parece com o seguinte:

#   pandas
import pandas as pd

#     csv-    -
# (        )
df_from_file1 = pd.read_csv('./example1_csv_1.csv', sep=';', encoding='utf-8',
                            usecols=['id', 'name', 'email', 'reg_date'])
df_from_file2 = pd.read_csv('./example1_csv_2.csv', sep=';', encoding='utf-8',
                            usecols=['id', 'name', 'email','reg_date'])
df_from_file3 = pd.read_csv('./example1_csv_3.csv', sep=';', encoding='utf-8',
                            usecols=['id', 'name', 'email', 'reg_date'])

#    -    - 
# (   union  SQL)
df_from_csv = pd.concat([df_from_file1, df_from_file2, df_from_file3]).\
    reset_index(drop=True)
print(df_from_csv)

#       
df_from_csv.drop_duplicates(subset='id', keep='first', inplace=True)
print(df_from_csv)

#     NaN ( )   reg_date
df_from_csv = df_from_csv.dropna()
print(df_from_csv)

#    Excel-   UI  -,
#       
# (        )
file_excel = 'report_UI.xlsx'
df_from_excel = pd.ExcelFile(file_excel).parse('1')
print(df_from_excel)

#  -     - 
# -       UI
# (   outer join  SQL)
df = df_from_csv.merge(df_from_excel, left_on='id', right_on="", how='outer')
print(df)

#     Excel-
writer = pd.ExcelWriter('.xlsx')
df.to_excel(writer, '1')
writer.save()

Limitações:

  • ( , 30 000 ).
  • ( Excel) / , .

Cenário No. 2
A seção contém dados na forma de uma tabela para certos objetos de uma única fonte. O sistema receberá dados de uma segunda fonte (integração) e atualizará os dados da tabela existente com esses dados. Cada registro na tabela são dados para um objeto que possui um identificador exclusivo. Se, a partir de uma nova fonte, os dados de um objeto por identificador coincidirem com os dados de um objeto existente, todos os campos de um registro existente serão atualizados com os dados de uma nova fonte (confirmada). Se a tabela ainda não tiver um objeto com um identificador da segunda fonte, um novo registro será criado na tabela com dados da nova fonte. Os dados do segundo sistema podem ser enviados para um arquivo json com antecedência.

A tarefa do testador:Prepare um arquivo com dados para o teste com antecedência, a fim de verificar se os registros existentes são atualizados corretamente e são afixados com um sinal de confirmação no banco de dados se houver uma correspondência por identificador. o identificador ainda não estava.

Nós compomos um script para o script:

  • Carregamos os dados da tabela de partição para o arquivo do Excel na interface do usuário (se isso não for possível, você sempre pode exportar os dados do resultado da consulta SQL usada no código para gerar dados para esta tabela na interface do usuário) e preenchê-los no primeiro quadro de dados .
  • Nós obtemos o arquivo json com dados da segunda fonte e o carregamos no segundo quadro de dados.
  • (merge — outer join SQL) - - Excel-, . , , .

:

  • ( , 30 000 ).
  • json- / – /, - json- pandas /.

Cenário 3

É feita uma solicitação para a API do sistema, em resposta à qual dados sobre objetos no formato json são recebidos.

Tarefa do testador: Compare os dados da resposta à solicitação à API com os dados do resultado da consulta SQL no banco de dados.

Nós compomos um script para o script:

  • Executamos a consulta SQL no banco de dados, exportamos os dados do resultado da consulta para um arquivo csv, carregamos esses dados no primeiro quadro de dados.
  • Nós salvamos os dados da resposta à solicitação para a API no arquivo json, carregamos os dados do arquivo no segundo quadro de dados.
  • Combinamos os dados (mesclagem - por analogia com junção externa no SQL) de dois quadros de dados recebidos em um novo quadro de dados por um identificador exclusivo e descarregamos os dados para um arquivo do Excel, no qual já comparamos dados por colunas usando as funções de Excel
  • Ou os dados nas colunas no quadro de dados geral podem ser comparados usando pandas, enquanto descarregam as linhas com os mesmos / diferentes dados nas colunas em um novo arquivo de quadro de dados / Excel para análise.

Dados de exemplo do arquivo example3_csv.csv :



Dados de exemplo do arquivo example3_json.json :

[
    {
        "id": "16421118-4116",
        "name_json": "Tempor Consulting",
        "email_json": "Nullam.lobortis.quam@***",
        "tel_json": "1-821-805-****",
        "reg_date_json": "12-11-16",
        "city_json": "Natales"
    },
    {
        "id": "16040210-2206",
        "name_json": "Odio Etiam Incorporated",
        "email_json": "arcu@***",
        "tel_json": "1-730-291-****",
        "reg_date_json": "26-06-05",
        "city_json": "Viddalba"
    },
...
]

O script python fica assim:

#   pandas
import pandas as pd

#    csv-  -
# (        )
#       csv-     ";"
df_from_csv = pd.read_csv('./example3_csv.csv', sep=';', encoding='utf-8')
print(df_from_csv)

#    json-  -
# (        )
df_from_json = pd.read_json('./example3_json.json', encoding='utf-8')
print(df_from_json)

#  -    -
# (   outer join  SQL)
df_csv_json = df_from_csv.merge(df_from_json, left_on='id', 
                                right_on="id", how='outer')
print(df_csv_json)

#    Excel-,   ,
#      -   ,
#          
# (      )
# writer = pd.ExcelWriter('.xlsx')
# df_csv_json.to_excel(writer, '1')
# writer.save()

#       
# (, name_csv  name_json) 
#       Excel-  
# (        )
unequal_data_df = df_csv_json.loc[df_csv_json['name_csv'] != 
                                  df_csv_json['name_json']]
unequal_data_df = unequal_data_df[['id', 'name_csv', 'name_json']]
print(unequal_data_df)

writer = pd.ExcelWriter('_name.xlsx')
unequal_data_df.to_excel(writer, '1')
writer.save()


Limitações:

  • Ao trabalhar com arquivos com um número muito grande de linhas, você precisará dividi-los em arquivos separados (aqui você precisa tentar, raramente tenho arquivos com mais de 30.000 linhas).
  • Se o arquivo json tiver vários níveis de aninhamento de objetos / matrizes de dados, a partir dos níveis internos eles serão carregados na célula como um objeto / matriz, portanto, trabalhar sem qualquer preparação com arquivos json usando pandas é conveniente apenas para dados sem aninhamento excessivo de objetos / matrizes.
  • API SQL- , SQL- .

Se a resposta à solicitação da API vier no formato xml, primeiro será necessário analisar os dados necessários do arquivo xml usando o ElementTree ou outra biblioteca e carregá-los no quadro de dados.

Cenário No. 4

Na interface do usuário, é baixado um arquivo xml com dados sobre objetos, que é gerado em tempo real a partir de dados no banco de dados sujeitos a determinadas condições (por exemplo, status, datas, anos ou outros valores de parâmetros para objetos são levados em consideração).

Tarefa do testador: Compare a identificação de identificadores exclusivos dos objetos do arquivo xml que estão no atributo da marca da empresa com os identificadores dos objetos do resultado da consulta SQL no banco de dados.

Nós compomos um script para o script:

  • Nós salvamos os dados da resposta à solicitação para a API no arquivo xml, obtemos os dados necessários desse arquivo usando a biblioteca ElementTree, carregamos os dados no primeiro quadro de dados.
  • Executamos a consulta SQL no banco de dados, exportamos os dados do resultado da consulta para o arquivo csv, carregamos esses dados no segundo quadro de dados.
  • Combinamos os dados (mesclagem - por analogia com junção externa no SQL) de dois quadros de dados recebidos em um novo quadro de dados por um identificador exclusivo e descarregamos os dados para um arquivo do Excel.
  • Em seguida, abra o arquivo resultante e analise as linhas de dados.

Dados de exemplo do arquivo example4_csv.csv :



Dados de exemplo do arquivo example4_xml.xml : Um



script python se parece com o seguinte:

#   ElementTree
from xml.etree import ElementTree
#   pandas
import pandas as pd

#    xml-   
# (        )
tree = ElementTree.parse("example4_xml.xml")

#   
root = tree.getroot()

#  ,     
data_list = []
i = 1

#    -   id_type1  id_type2
for child in root.iter("companies"):
    for child_1 in child.iter("company"):
            data_list.append({"": i, "id": child_1.get("id_type1")
                                                or child_1.get("id_type2"), 
                              "  xml": ""})
            i += 1

#     data_list  -
df_from_xml = pd.DataFrame.from_dict(data_list, orient='columns')
print(df_from_xml)

#    csv-  -
df_from_csv = pd.read_csv('./example4_csv.csv', sep=';', encoding='utf-8')
print(df_from_csv)

#  -   -
# (   outer join  SQL)
df = df_from_csv.merge(df_from_xml, left_on='id', right_on="id", how='outer')
print(df)

#    Excel-
#          
# (      )
writer = pd.ExcelWriter('.xlsx')
df.to_excel(writer, '1')
writer.save()

Cenário 5

Na interface do usuário, a seção exibe dados sobre objetos na forma de uma tabela. É possível fazer upload de dados para um arquivo do Excel.

A tarefa do testador: Compare os dados da tabela de partição com os dados baixados no arquivo do Excel.

Nós compomos um script para o script:

  • Pedimos aos desenvolvedores uma consulta SQL no banco de dados a partir do código responsável pela saída de dados para a tabela de partições na interface do usuário.
  • Executamos essa consulta SQL no banco de dados, carregamos os dados em um arquivo csv, carregamos os dados dele no primeiro quadro de dados.
  • Carregamos os dados da tabela de partição para o arquivo do Excel na interface do usuário e carregamos os dados para o segundo quadro de dados.
  • (merge — outer join SQL) - - Excel-, Excel.
  • - pandas, / -/Excel- .

:

  • , Excel- UI, , , .

Além disso, scripts semelhantes podem ser usados ​​simplesmente para transferir dados de arquivos json ou arquivos csv para arquivos do Excel. Ou, você pode combinar dados de vários arquivos do Excel em determinadas colunas e carregá-los em um novo arquivo do Excel.

Conclusão


Estes são apenas alguns exemplos de como você pode usar python + pandas para acelerar o processo de teste e encontrar bugs. De fato, os pandas têm muito mais oportunidades para trabalhar com dados. Você pode ler mais sobre isso na documentação desta biblioteca.

Talvez seu projeto tenha outras opções para usar esses scripts e este artigo o ajude a começar a usá-los no trabalho dos testadores.

Source: https://habr.com/ru/post/undefined/


All Articles