【问题标题】:Best practice for testing reports测试报告的最佳实践
【发布时间】:2014-12-11 14:45:46
【问题描述】:

有没有人有关于如何测试庞大数据集的最佳实践?

例如,我有一个运行此 SQL 的报表页面:

SELECT COUNT(DISTINCT order_items.id) AS order_items,
       DATE(order_items.created_on)   AS date
FROM orders
JOIN order_items                  ON order_items.order_id = orders.id
JOIN shipments                    ON shipments.id = order_items.shipment_id
JOIN transactions                 ON transactions.order_id = orders.id
JOIN customers                    ON customers.id = orders.customer_id
LEFT JOIN flagged_transactions ON flagged_transactions.transaction_id = transactions.id
WHERE orders.state NOT IN ('a', 'b', 'c', '')
 AND customers.state NOT IN ('fraud', 'maybe_fraud')
 AND shipments.state NOT IN ('cancelled', 'shipped')
 AND shipments.vendor_id = %{some_vendor}
 AND order_items.quantity > 0
 AND order_items.state IN ('initial', 'approve')
 AND order_items.created_on BETWEEN %{start_date} AND %{end_date}
 AND (flagged_transactions.id IS NULL OR flagged_transactions.state NOT IN ('pending'))
GROUP BY date
ORDER BY date

在规范中,这变成了一大堆工厂,每个对象一个或几个。

有没有人有关于如何更优雅地做到这一点的想法或最佳实践?

【问题讨论】:

  • 您正在访问一个庞大的生产型数据库吗?相反,请创建一个小型测试数据库,其中只包含一个或几个可能的查询结果。
  • 单元测试旨在测试代码,而不是数据。您需要为每个场景模拟数据,并测试您是否获得了预期的结果。模拟数据需要是您要测试的场景的最小示例。
  • 谢谢@theTinMan,但我当然只打测试数据库。我的问题是关于如何优雅地播种这个数据库而不是调用大量工厂。
  • @UriAgassi,您建议模拟来自数据库的响应并使用模拟响应。但是,当架构有可能更改并且不能防止错误的 SQL 查询时,这并没有多大帮助。因此,将来重构会很危险。
  • @sharkzp - 测试与模式的兼容性不是单元测试的一部分。它更像是系统测试或集成测试。这个测试应该只是看到查询通过,而不是它工作。

标签: ruby-on-rails ruby unit-testing rspec


【解决方案1】:

您可以采用的几种技术:

  • 为将出现在结果集中的订单定义高级工厂,即不会被 where 子句过滤掉。有一些参数是可定制的,比如日期。通过对报告有意义的名称引用工厂
  • 将查询 where 子句拆分为不同的方法,以便您可以分别测试过滤和聚合。这将允许您使用较小的数据集进行测试,因为您不需要汇总大量数据来证明所有过滤器都有效
  • 中断管道中的过滤器,将其添加回下一个过滤器。例如:排除欺诈客户、排除标记的交易、排除已发货或已取消的发货,以及每一步添加到要排除的 id。这样,您可以使用更简单的工厂独立测试每个部分。这可能会对性能产生积极或消极的影响,具体取决于您的数据集
  • 只有基本的测试覆盖率证明涵盖了快乐路径和最常见的情况

【讨论】:

  • 感谢@rafb3,但拆分此 SQL 会降低其性能。不幸的是,由于对象实例化和许多其他小事情,arel/sequel/active_record 都不能快速执行和生成报告。但总体来说你的想法不错。
最近更新 更多