gpt4 book ai didi

unit-testing - 如何通过单元测试让高效的代码出现?

转载 作者:行者123 更新时间:2023-12-03 00:28:17 26 4
gpt4 key购买 nike

我参加了 TDD 编码道场,我们尝试在简单问题上练习纯 TDD。然而,我发现单元测试中出现的代码并不是最有效的。现在,大多数情况下这都很好,但是如果代码使用量增加而导致效率成为问题怎么办?

我喜欢单元测试中出现代码的方式,但是是否有可能通过进一步的测试来体现效率属性?

这是 ruby​​ 中的一个简单示例:素因数分解。我遵循一种纯粹的 TDD 方法,使测试一个接一个地通过,验证了我最初的验收测试(在底部注释)。如果我想制作 generic prime factorization algorithms 之一,我可以采取哪些进一步的步骤出现?为了减少问题域,假设我想得到 quadratic sieve实现...现在,在这种精确的情况下,我知道“最佳算法”,但在大多数情况下,客户端只需添加一个要求,即该功能在给定环境下运行的时间少于“x”时间。

require 'shoulda'
require 'lib/prime'

class MathTest < Test::Unit::TestCase
context "The math module" do
should "have a method to get primes" do
assert Math.respond_to? 'primes'
end
end
context "The primes method of Math" do
should "return [] for 0" do
assert_equal [], Math.primes(0)
end
should "return [1] for 1 " do
assert_equal [1], Math.primes(1)
end
should "return [1,2] for 2" do
assert_equal [1,2], Math.primes(2)
end
should "return [1,3] for 3" do
assert_equal [1,3], Math.primes(3)
end
should "return [1,2] for 4" do
assert_equal [1,2,2], Math.primes(4)
end
should "return [1,5] for 5" do
assert_equal [1,5], Math.primes(5)
end
should "return [1,2,3] for 6" do
assert_equal [1,2,3], Math.primes(6)
end
should "return [1,3] for 9" do
assert_equal [1,3,3], Math.primes(9)
end
should "return [1,2,5] for 10" do
assert_equal [1,2,5], Math.primes(10)
end
end
# context "Functionnal Acceptance test 1" do
# context "the prime factors of 14101980 are 1,2,2,3,5,61,3853"do
# should "return [1,2,3,5,61,3853] for ${14101980*14101980}" do
# assert_equal [1,2,2,3,5,61,3853], Math.primes(14101980*14101980)
# end
# end
# end
end

以及我通过这种方法创建的朴素算法

module Math
def self.primes(n)
if n==0
return []
else
primes=[1]
for i in 2..n do
if n%i==0
while(n%i==0)
primes<<i
n=n/i
end
end
end
primes
end
end
end

编辑1从第一个答案来看,我想我最初的描述不清楚:性能测试不是我的单元测试的标准部分,这是一个新的验收测试,旨在回答客户的特定要求

编辑2我知道如何测试执行时间,但似乎从平凡算法转向优化算法是一大步。我的问题是如何使最佳代码出现,换句话说:如何分解从平凡代码到最佳代码的迁移?有人提到这是一个特定于问题的方法:我提供了一个示例问题,但我不知道如何继续。

最佳答案

  • TDD 用于正确性非回归,并专注于单元测试
  • 分析是为了性能,它是一个功能测试问题。

我还曾经参加过每周一次的 TDD 编码道场,我们尝试了一些实验,看看是否可以将其用于算法目的(找到更好的算法,找到没有明显算法的算法)或内置性能限制。

在 Dojo 中使用 TDD 时,我们尝试遵循以下规则

  • 编写最简单的测试来破坏现有代码(如果不破坏代码,就付一瓶啤酒)
  • 编写使测试通过的最简单代码
  • 在添加测试之前重构代码(使用代码气味)
  • 在添加新测试之前还要重构测试

鉴于这些规则,我们有比乍一看显而易见的更多的实验空间。我们可以调整最简单的定义并添加代码气味以考虑效率(基本上:如果我们想到几种简单的方法来实现某些更喜欢最有效的方法,并且如果我们知道一些更有效的但仍然简单的众所周知的算法与我们代码中使用的相比,它是一种气味)。

总而言之,结果是 TDD 本身不太适合预测整体代码性能并从一开始就实现高效的代码,即使使用 TDD 和重构我们成功地获得了对代码的更好洞察,并可以增强它以实现更好的可读性< em>并避免一些明显的性能瓶颈。尝试在该测试级别的代码中插入性能约束通常是灾难性的(我们的代码和测试过于复杂,并且经常损坏代码或过于复杂而无法更改)。

一个原因是 TDD 我们通常使用非常小的测试集(失败的最简单的测试)。另一方面,真实数据集会出现更多的性能问题,并且它与上述规则非常不相符。性能测试,即使形式上仍然是单元测试,也更类似于功能测试。常见的优化策略包括添加缓存,或者考虑实际数据分布的某些属性,或者当某些小的好处功能对性能产生很大的负面影响时协商用户故事的更改。所有这些都不能真正内置在 TDD 中,但更有可能在分析代码时找到。

我相信性能目标基本上是一个功能测试问题。

关于unit-testing - 如何通过单元测试让高效的代码出现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2625535/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com