数据工程中的单元测试完全指南

news2024/12/23 10:31:48

在数据工程领域中,经常被忽视的一项实践是单元测试。许多人可能认为单元测试仅仅是一种软件开发方法论,但事实远非如此。随着我们努力构建稳健、无错误的数据流水线和SQL数据模型,单元测试在数据工程中的价值变得越来越清晰。

本文带你深入探索如何将这些成熟的软件工程实践应用到数据工程中。

1 单元测试的重要性

在数据工程的背景下,采用单元测试可以确保您的数据和业务逻辑的准确性,进而产出高质量的数据,获得您的数据分析师、科学家和决策者对数据的信任。

2 单元测试数据流水线

数据流水线通常涉及复杂的数据抽取、转换和加载(ETL)操作序列,出错的可能性很大。为了对这些操作进行单元测试,我们将流水线拆分为单个组件,并对每个组件进行独立验证。

以一个简单的流水线为例,该流水线从CSV文件中提取数据,通过清除空值来转换数据,然后将其加载到数据库中。以下是使用pandas的基于Python的示例:

import pandas as pd
  from sqlalchemy import create_engine
  # 加载CSV文件的函数
  def load_data(file_name):
      data = pd.read_csv(file_name)
      return data
  # 清理数据的函数
  def clean_data(data):
      data = data.dropna()
      return data
  # 将数据保存到SQL数据库的函数
  def save_data(data, db_string, table_name):
      engine = create_engine(db_string)
      data.to_sql(table_name, engine, if_exists='replace')
  # 运行数据流水线
  data = load_data('data.csv')
  data = clean_data(data)
  save_data(data, 'sqlite:///database.db', 'my_table')

为了对这个流水线进行单元测试,我们使用像pytest这样的库为每个函数编写单独的测试。

在这个示例中,有三个主要的函数:load_data、clean_data和save_data。我们会为每个函数编写测试。对于load_data和save_data,需要设置一个临时的CSV文件和SQLite数据库,可以使用pytest库的fixture功能来实现。

import os
  import pandas as pd
  import pytest
  from sqlalchemy import create_engine, inspect
  # 使用pytest fixture来设置临时的CSV文件和SQLite数据库
  @pytest.fixture
  def csv_file(tmp_path):
      data = pd.DataFrame({
          'name': ['John', 'Jane', 'Doe'],
          'age': [34, None, 56]  # Jane的年龄缺失
      })
      file_path = tmp_path / "data.csv"
      data.to_csv(file_path, index=False)
      return file_path
  @pytest.fixture
  def sqlite_db(tmp_path):
      file_path = tmp_path / "database.db"
      return 'sqlite:///' + str(file_path)
  def test_load_data(csv_file):
      data = load_data(csv_file)
      
      assert 'name' in data.columns
      assert 'age' in data.columns
      assert len(data) == 3
  def test_clean_data(csv_file):
      data = load_data(csv_file)
      data = clean_data(data)
      
      assert data['age'].isna().sum() == 0
      assert len(data) == 2  # Jane的记录应该被删除
  def test_save_data(csv_file, sqlite_db):
      data = load_data(csv_file)
      data = clean_data(data)
      save_data(data, sqlite_db, 'my_table')
      
      # 检查数据是否保存正确
      engine = create_engine(sqlite_db)
      inspector = inspect(engine)
      tables = inspector.get_table_names()
      
      assert 'my_table' in tables
      
      loaded_data = pd.read_sql('my_table', engine)
      assert len(loaded_data) == 2  # 只应该存在John和Doe的记录

这里是另一个例子:假设您有一个从CSV文件中加载数据并将其中的“日期”列从字符串转换为日期时间的流水线:

def convert_date(data, date_column):
      data[date_column] = pd.to_datetime(data[date_column])
      return data

为上述函数编写的单元测试将传入具有已知日期字符串格式的DataFrame。然后,它将验证函数是否正确将日期转换为日期时间对象,并且它是否适当处理无效格式。

我们为上述场景编写一个单元测试。该测试首先使用有效日期检查函数,断言输出DataFrame中的“date”列确实是datetime类型,并且值与预期相符。然后,它检查在给出无效日期时,函数是否正确引发了ValueError。

import pandas as pd
  import pytest
  def test_convert_date():
      # 使用有效日期进行测试
      test_data = pd.DataFrame({
          'date': ['2021-01-01', '2021-01-02']
      })
      
      converted_data = convert_date(test_data.copy(), 'date')
      
      assert pd.api.types.is_datetime64_any_dtype(converted_data['date'])
      assert converted_data.loc[0, 'date'] == pd.Timestamp('2021-01-01')
      assert converted_data.loc[1, 'date'] == pd.Timestamp('2021-01-02')
      # 使用无效日期进行测试
      test_data = pd.DataFrame({
          'date': ['2021-13-01']  # 这个日期是无效的,因为没有第13个月
      })
      
      with pytest.raises(ValueError):
          convert_date(test_data, 'date')

以下是最后一个例子:假设您有一个加载数据并进行聚合的流水线,计算每个地区的总销售额:

def aggregate_sales(data):
      aggregated = data.groupby('region').sales.sum().reset_index()
      return aggregated

为该函数编写的单元测试将向其传递具有各个地区销售数据的DataFrame。测试将验证函数是否正确计算每个地区的总销售额。

我们为该函数编写一个单元测试。在这个测试中,我们首先向aggregate_sales函数传递一个具有已知销售数据的DataFrame,并检查它是否正确聚合了销售额。然后,向其传递一个没有销售数据的DataFrame,并检查它是否正确将这些销售额聚合为0。这样可以确保函数正确处理典型情况和边缘情况。

以下是使用pytest库为aggregate_sales函数编写单元测试的示例:

import pandas as pd
  import pytest
  def test_aggregate_sales():
      # 各个地区的销售数据
      test_data = pd.DataFrame({
          'region': ['North', 'North', 'South', 'South', 'East', 'East', 'West', 'West'],
          'sales': [100, 200, 300, 400, 500, 600, 700, 800]
      })
      
      aggregated = aggregate_sales(test_data)
      
      assert aggregated.loc[aggregated['region'] == 'North', 'sales'].values[0] == 300
      assert aggregated.loc[aggregated['region'] == 'South', 'sales'].values[0] == 700
      assert aggregated.loc[aggregated['region'] == 'East', 'sales'].values[0] == 1100
      assert aggregated.loc[aggregated['region'] == 'West', 'sales'].values[0] == 1500
      # 没有销售数据的测试
      test_data = pd.DataFrame({
          'region': ['North', 'South', 'East', 'West'],
          'sales': [0, 0, 0, 0]
      })
      
      aggregated = aggregate_sales(test_data)
      
      assert aggregated.loc[aggregated['region'] == 'North', 'sales'].values[0] == 0
      assert aggregated.loc[aggregated['region'] == 'South', 'sales'].values[0] == 0
      assert aggregated.loc[aggregated['region'] == 'East', 'sales'].values[0] == 0
      assert aggregated.loc[aggregated['region'] == 'West', 'sales'].values[0] == 0

感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!有需要的小伙伴可以点击下方小卡片领取 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1031428.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安卓桌面记事本便签软件哪个好用?

日常生活及工作中,很多人常常会遇到一些一闪而现的灵感,这时候拿出手机想要记录时,却找不到记录的软件。在这个快节奏的时代,安卓手机是我们日常生活不可或缺的伙伴。然而,正因为我们的生活如此忙碌,记事变…

从 Hackathon 战队到创业公司,和开发者们聊聊真实世界 AI Apps 的基础设施丨活动预告

在不久前结束的 TiDB Future App Hackath on 2023 上,来自全球 88 个国家的 1492 名参赛者们借助 AI 和 TiDB Serverless 的能力,构建了许多令人印象深刻的项目。 打造 Hackathon 的项目是一个从 0-1 的过程,真实世界中也涌现出了一批创业公…

Java 21正式发布了,来来来,一睹它的芳容!

Oracle 高兴地宣布 JDK 21 已经正式上线了。这是按照每六个月一次的发布计划,准时推出的第 12 个版本。这种定期的发布模式为开发者提供了稳定和可预见的创新,使得他们可以轻松地接纳和采用这些新特性。 Java 由于其出色的性能、稳定性和安全性使其持续成为全球最受欢迎的编程…

启山智软/微信小程序商城源码(微信小程序)

文章目录 启山智软一、小程序商城首页二、小程序商城分类三、小程序商城我的源码获取 启山智软 想要了解代码规范,学习商城解决方案,点击下方官网链接联系客服 作者:启山智软 官网及博客:启山智软官网、CSDN、掘金、gitee 简介&a…

爱分析《商业智能最佳实践案例》

近日,国内知名数字化市场研究咨询机构爱分析发布《2023爱分析商业智能最佳实践案例》,此评选活动面向落地商业智能的各行企业和商业智能厂商,以第三方专业视角深入调研,评选出具有参考价值的创新案例。永达汽车集团与数聚股份合作…

【Zabbix监控一】zabbix的原理与安装

利用一个优秀的监控软件,我们可以: ●通过一个友好的界面进行浏览整个网站所有的服务器状态 ●可以在 Web 前端方便的查看监控数据 ●可以回溯寻找事故发生时系统的问题和报警情况 总结:zabbix主要功能 监控,cpu负载,内存使用&a…

了解:组件和组件的值的分享

<template><Block title"热门公司"><div slot"content" class"container"><CompanyList :company-list"currentPageCompany"></CompanyList><div class"pagination"><el-pagination…

【高级IO】第一讲(5种IO模型的介绍、select函数介绍、一个简单select服务器)

高级IO 1.五种IO模型介绍2.Select函数介绍 1.五种IO模型介绍 点击跳转: 5种I/O模型 2.Select函数介绍 点击跳转: 【Linux】——select详解

LeetCode 接雨水 双指针

原题链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题面&#xff1a; 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a…

2023华为杯研究生数学建模C题分析

完整的分析查看文末名片获取&#xff01; 问题一 在每个评审阶段&#xff0c;作品通常都是随机分发的&#xff0c;每份作品需要多位评委独立评审。为了增加不同评审专家所给成绩之间的可比性&#xff0c;不同专家评审的作品集合之间应有一些交集。但有的交集大了&#xff0c;则…

git 常用命令分享

git官网地址&#xff1a;https://git-scm.com/ 1.设置用户名 邮箱 设置用户名: git config --global user.name “name” 设置邮箱&#xff1a; git config --global user.email "email" 2.查看设置的信息 git config --list 以上设置的信息在用户目录下&#xff1…

Python —— pytest框架

1、认识pytest框架 1、搭建自动化框架的思路与流程 1、搭建自动化测试框架的思路和流程&#xff0c;任意测试手段流程都是一致的&#xff1a;手工测试、自动化测试、工具测试 手工测试&#xff1a;熟悉业务 —— 写用例 —— 执行用例并记录结果 —— 生成测试报告自动化测试…

DETR纯代码分享(八)position_encoding.py(models)

一、导入一些Python库和模块 import math import torch from torch import nnfrom util.misc import NestedTensor 上面的代码段主要是Python代码&#xff0c;用于导入一些Python库和模块&#xff0c;以下是对每行代码的详细解释&#xff1a; import math: 这一行代码导入了P…

Node.js VS Python:程序员该选择哪个作为爬虫语言?

对于程序员来说&#xff0c;选择合适的语言作为爬虫开发工具很重要。在这篇文章中&#xff0c;我们将探讨使用Node.js和Python进行爬虫开发的优势和劣势&#xff0c;帮助你做出明智的选择&#xff0c;并提供一些实际操作价值的建议。 一、Node.js的优势与劣势 1、优势&#xf…

《Playing repeated games with Large Language Models》全文翻译

《Playing repeated games with Large Language Models》- 使用大型语言模型玩重复游戏 论文信息摘要1. 介绍2. 相关工作3. 一般方法4. 分析不同游戏系列的行为5. 囚徒困境5.1 性别之战 6. 讨论 论文信息 题目&#xff1a;《Playing repeated games with Large Language Model…

勇立潮头!高品质SFT语音数据实现Zero-Shot语音复刻大模型

文本到语音合成&#xff08;Text to Speech&#xff0c;TTS&#xff09;作为生成式人工智能&#xff08;Generative AI 或 AIGC&#xff09;的重要课题&#xff0c;在近年来取得了飞速发展。为了实现高效合成既自然又高质量的人类语音&#xff0c;有不少机构及企业都进行了相关…

安防监控视频AI智能分析网关:人流量统计算法的应用场景汇总

TSINGSEE青犀人流量检测算法是内置在智能分析网关中的一种能够通过AI分析和计算人群数量以及密度的算法技术&#xff0c;在提升城市管理效率、改善用户体验和增加安全性方面发挥着重要作用。人流量检测算法在许多领域都有广泛的应用&#xff0c;如智慧城市、智慧交通、智慧景区…

计算机网络运输层网络层补充

1 CDMA是码分多路复用技术 和CMSA不是一个东西 UPD是只确保发送 但是接收端收到之后(使用检验和校验 除了检验的部分相加 对比检验和是否相等。如果不相同就丢弃。 复用和分用是发生在上层和下层的问题。通过比如时分多路复用 频分多路复用等。TCP IP 应用层的IO多路复用。网…

微软宣布推广数字助理 Copilot;GPT 应用开发和思考

&#x1f989; AI新闻 &#x1f680; 微软宣布推广基于生成式人工智能的数字助理 Copilot 摘要&#xff1a;微软宣布将基于生成式人工智能的数字助理 Copilot 推广到更多软件产品中。新的 AI 助理 Microsoft Copilot 将在 Windows 中无缝可用&#xff0c;包括 Windows 11 桌面…

【校招VIP】专业课考点之TCP连接

考点介绍&#xff1a; 在TCP&#xff0f;IP中&#xff0c;TCP协议通过三次握手来建立连接&#xff0c;从而提供可靠的连接服务。本专题主要介绍一线互联网大厂面试关于TCP连接的相关问题。 专业课考点之TCP连接-相关题目及解析内容可点击文章末尾链接查看&#xff01; 一、考…