加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

单元测试 – 如何通过单元测试产生高效的代码?

发布时间:2020-12-14 04:48:13 所属栏目:百科 来源:网络整理
导读:我参加了一个TDD Coding Dojo,我们尝试在简单的问题上练习纯TDD.然而,对我来说,单元测试中出现的代码并不是最有效的.现在大部分时间这都很好,但如果代码使用量增加以致效率成为问题会怎样. 我喜欢代码从单元测试中出现的方式,但是有可能通过进一步的测试来提
我参加了一个TDD Coding Dojo,我们尝试在简单的问题上练习纯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,Math.primes(4)
    end 
    should "return [1,5] for 5" do 
      assert_equal [1,5],Math.primes(5)
    end   
    should "return [1,3] for 6" do 
      assert_equal [1,Math.primes(6)
    end       
    should "return [1,3] for 9" do 
      assert_equal [1,3,Math.primes(9)
    end        
    should "return [1,5] for 10" do 
      assert_equal [1,Math.primes(10)
    end                  
  end
#  context "Functionnal Acceptance test 1" do
#    context "the prime factors of 14101980 are 1,5,61,3853"do      
#      should "return  [1,3853] for ${14101980*14101980}" do
#        assert_equal [1,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,我们尝试了一些实验,看看是否有可能将它用于算法目的(找到更好的算法,找到没有明显算法的算法)或内置性能约束.

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

>编写最简单的测试,打破现有代码(如果不破坏代码,则支付啤酒)
>编写使测试通过的最简单的代码
>在添加测试之前重构代码(使用代码味道)
>在添加新测试之前还要进行重构测试

鉴于这些规则,我们有更多的实验空间,而不是一见钟情.我们可以调整最简单的定义并添加代码气味以考虑效率(基本上:如果我们想到几种简单的方法来实现更有效的东西,如果我们知道一些更有效 – 但仍然很简单的知识 – 算法比我们的代码中使用的那个,它是一种气味).

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

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

我相信表演目标基本上是一个功能测试问题.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读