• 使用Enumerable模块实现简单的测试框架并进行数据统计


    Ruby核心库中的Enumerable模块可能听起来很陌生,但实际上大家是应该经常接触到的。这里简单总结一下Enumerable模块的常用方法。

    The Enumerable mixin provides collection classes with several traversal and searching methods, and with the ability to sort. The class must provide a method each, which yields successive members of the collection. If Enumerable#max, min, or sort is used, the objects in the collection must also implement a meaningful <=> operator, as these methods rely on an ordering between members of the collection.

    Enumerable模块提供了一系列的迭代器方法。使用Enumerable模块很简单,只需要如下步骤:

    • mixin Enumerable模块;

    • 在使用Enumerable模块的类中定义each方法,保证each方法能够迭代该类中的所有元素;

    • 如果需要使用max min sort等方法的话,那么需要定义<=>方法;

    <=>方法一般有1个参数且称之为other,如果self > other,则返回1;self == other则返回0,否则返回-1。(这样解释实际上是很不严谨的,但是为了方便可以如此简单理解,高手请尽情鄙视吧...)

    下面是简单的用法。下面的代码实现了简单的测试框架——测试用例及测试用例集,我们可以看到Enumerable模块中定义的方法在统计结果时发挥了重要的作用:

    require 'pp'
    Object.method_undefined(:assert_true) if Object.method_defined?(:assert_true)
    Object.method_undefined(:assert_false) if Object.method_defined?(:assert_false)
     
    Object.module_eval do
      def assert_true 
        self == true
      end
     
      def assert_false
        self == false
      end  
    end
     
    class TestCase
      attr_accessor :priority 
      attr_reader :execute_time, :name, :test_result
     
      def initialize(name, priority, &case_step)
        @name = name
        @priority = priority
        @case_step = case_step
      end
     
      def <=>(other)
        @priority <=> other.priority
      end
     
      def execute    
        @test_result = @case_step.call
        @execute_time = @priority
      end
    end
     
    class TestCaseGroup
      include Enumerable
     
      attr_reader :test_cases, :test_result
     
      def initialize 
        @test_cases = []
        @test_result = {}
      end
     
      def add_case *test_case
        test_case.each do |c|
          @test_cases << c
        end
      end
     
      def delete_case test_cases
        @test_cases.delete test_cases
      end
     
      def each(&block)
        @test_cases.each &block
      end
     
      def execute
        @test_cases.each do |c|
          @test_result[c.name.to_sym] = c.execute
        end    
      end    
    end
     
    #定义具体用例
    case1 = TestCase.new('case1', 1) do
      (1 > 1).assert_false
    end
     
    case2 = TestCase.new('case2', 2) do
      (1 > 1).assert_true
    end
     
    case3 = TestCase.new('case3', 3) do
      (1 == 1).assert_true
    end
     
    #创建用例组并添加用例
    test_group = TestCaseGroup.new
    test_group.add_case case1, case2, case3
     
    #执行用例并输出结果
    test_group.execute
    p test_group.test_result
     
    #是否有case的执行时间大于2?
    #from Enumerable
    pp test_group.any? {|c| c.execute_time > 2}
     
    #是否有case失败
    #from Enumerable
    pp test_group.any? {|c| c.test_result.eql? false}
     
    #统计总共执行时间
    #from Enumerable
    puts test_group.inject(0){|total, c|total + c.execute_time}
     
    #按执行时间长短分组
    #小于等于2的一组,其他的一组
    pp test_group.partition{|c| c.execute_time < 2}
    

    Enumerable模块中提供了大量的实用迭代方法。这里用到到any? all? inject partition方法只是冰山一角而已。

    其他的如each_with_index,collect等方法应用也非常广泛。总而言之Enumerable模块是需要下功夫掌握的1个模块。

  • 相关阅读:
    wpf中防止界面卡死的写法
    wpf list<T>与ObservableCollection<T>的区别
    wpf 将对象按照正圆的顺序排列的写法
    .net 如何高效地使用string(转)
    wpf 查找DataTemplate中的控件的实现方式
    wpf 属性变更通知类的实现
    wpf 3D图形的实现(转)
    SpringBoot之HandlerInterceptorAdapter
    websocket简单实现
    mockjs基本使用
  • 原文地址:https://www.cnblogs.com/nbkhic/p/2229427.html
Copyright © 2020-2023  润新知