Ruby元編程:動態添加類屬性及其實際應用

上個星期測試道的Monkey老師和我聊到測試用例參數過多的問題,其實這樣的問題在我這裏也一樣經歷過。好比個人測試用例必須面對不一樣的測試環境,每一個環境有無數的參數,開發的最初階段,由於參數少,因此就放在執行的命令行裏,隨着測試用例的不斷增加,參數從4-5個增加到30多個,並且每一個用例使用的參數也不徹底相同,有使用ABCD的,有使用ADHJ的。另外有些參數想傳一個數組進去,用命令行參數的方法就很難處理。編程

通過考慮,果斷的使用配置文件來解決問題。選擇配置文件當時有兩個方案,一個是直接寫成Ruby代碼,可是考慮到要和自動化測試框架共享配置文件,因此最後決定使用YAML格式。Ruby對YAML的支持很是好,你能夠用以下方式訪問某個配置參數Configs['Host']['IP'],考慮到讓咱們的測試代碼更直觀,咱們但願能用Configs.Host_IP的方式訪問環境參數。數組

YAML配置文件例子:ruby

Storage:
  IP: 192.168.1.1
  Port: 80
  SSL_Port: 443
  Service_Port: 2000

DB:
  IP: 192.168.1.2
  User: Tom
  Password: test

Manifests:
  - IP: 192.168.2.1
  - IP: 192.168.2.2
  - IP: 192.168.2.3
  - IP: 192.168.2.4

咱們但願能用Configs.Storage_IP,Configs.DB_Password這樣的方法拿到參數,對於Manifests,咱們的輸入是數組,則但願能用Configs.Manifests[i]['IP']的方式訪問。利用Ruby的元編程特性,在咱們讀取YAML文件解析生成數組後,咱們就能夠遍歷每一個元素而後動態爲Configs添加屬性。代碼以下:框架

 1 require 'yaml'
 2 
 3 module ConfigParser
 4   class << self
 5     def add_attribute(klass, symbol)
 6       codes = %Q{
 7         def #{symbol}
 8           return @#{symbol}
 9         end
10         
11         def #{symbol}=(value)
12           @#{symbol} = value
13         end
14       }
15 
16       klass.instance_eval(codes)
17     end
18 
19     def expand_configs(configs = {})
20       configs.each do |key, value|
21         expand_sub_configs(key, value)
22       end  
23     end
24     
25     def expand_sub_configs(prefix, configs)
26       if configs.class != Hash
27         add_attribute(Configs, prefix)
28         eval("Configs.#{prefix} = configs")
29       else
30         configs.each do |key, value|
31           expand_sub_configs(prefix + '_' + key, value)
32         end
33       end
34     end
35   end 
36 end
37 
38 if ARGV.size != 1
39   puts "Usage: ..."
40   exit(-1)
41 end
42 
43 Configs = Class.new
44 
45 ConfigParser.expand_configs(YAML.load(File.open(ARGV[0])))
46 
47 puts 'Storage information:'
48 puts " #{Configs.Storage_IP}"
49 puts "  #{Configs.Storage_Port}"
50 puts "  #{Configs.Storage_SSL_Port}"
51 puts "  #{Configs.Storage_Service_Port}\n"
52 
53 puts 'DB information: '
54 puts "  #{Configs.DB_IP}"
55 puts "  #{Configs.DB_User}"
56 puts "  #{Configs.DB_Password}\n"
57 
58 puts 'Manifests information: '
59 Configs.Manifests.each do |info|
60   info.each do |k, v|
61     puts "  #{k}: #{v}"
62   end
63 end

執行命令ruby test.rb config.yml獲得輸出以下:測試

Storage information:
 192.168.1.1
  80
  443
  2000
DB information: 
  192.168.1.2
  Tom
  test
Manifests information: 
  IP: 192.168.2.1
  IP: 192.168.2.2
  IP: 192.168.2.3
  IP: 192.168.2.4
相關文章
相關標籤/搜索