kpi 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/app/models/kpi/report.rb +11 -11
- data/lib/kpi/memoizable.rb +109 -0
- data/lib/kpi.rb +3 -2
- metadata +61 -124
- data/test/test_helper.rb +0 -11
- data/test/unit/kpi/entry_test.rb +0 -66
- data/test/unit/kpi/merged_report_test.rb +0 -207
- data/test/unit/kpi/report_test.rb +0 -105
data/app/models/kpi/report.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
module KPI
|
2
2
|
class Report
|
3
3
|
extend KPI::Report::SuppressMemoization
|
4
|
-
extend
|
5
|
-
|
4
|
+
extend KPI::Memoizable
|
5
|
+
|
6
6
|
include KPI::Report::DynamicDefinitions
|
7
|
-
|
7
|
+
|
8
8
|
blacklist :initialize, :collect!, :entries, :time, :title, :defined_kpis, :result, :method_missing
|
9
|
-
|
9
|
+
|
10
10
|
def initialize(*args)
|
11
11
|
@options = args.extract_options!
|
12
12
|
@time = @options[:time] || Time.now
|
13
13
|
@title = @options[:title] || self.class.name
|
14
14
|
end
|
15
15
|
attr_reader :time, :title
|
16
|
-
|
16
|
+
|
17
17
|
def collect!
|
18
18
|
self.defined_kpis.each {|kpi_method| send(kpi_method) }
|
19
19
|
self
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def entries
|
23
23
|
Enumerator.new do |yielder|
|
24
24
|
self.class.defined_kpis.each do |kpi_method|
|
@@ -26,7 +26,7 @@ module KPI
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def defined_kpis
|
31
31
|
self.class.defined_kpis.map(&:to_sym)
|
32
32
|
end
|
@@ -34,16 +34,16 @@ module KPI
|
|
34
34
|
def result(*args)
|
35
35
|
KPI::Entry.new *args
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
def method_missing(name, *args)
|
39
39
|
# check if KPI exists in report if name of missing method has trailing '?'
|
40
40
|
return kpi_exists?($1.to_sym) if (/(.*)\?/ =~ name.to_s)
|
41
41
|
super
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
private
|
45
|
-
|
46
|
-
def kpi_exists?(name)
|
45
|
+
|
46
|
+
def kpi_exists?(name)
|
47
47
|
self.defined_kpis.include?(name.to_sym)
|
48
48
|
end
|
49
49
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'active_support/core_ext/kernel/singleton_class'
|
2
|
+
require 'active_support/core_ext/module/aliasing'
|
3
|
+
|
4
|
+
module KPI
|
5
|
+
module Memoizable
|
6
|
+
def self.memoized_ivar_for(symbol)
|
7
|
+
"@_memoized_#{symbol.to_s.sub(/\?\Z/, '_query').sub(/!\Z/, '_bang')}".to_sym
|
8
|
+
end
|
9
|
+
|
10
|
+
module InstanceMethods
|
11
|
+
def self.included(base)
|
12
|
+
base.class_eval do
|
13
|
+
unless base.method_defined?(:freeze_without_memoizable)
|
14
|
+
alias_method_chain :freeze, :memoizable
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def freeze_with_memoizable
|
20
|
+
memoize_all unless frozen?
|
21
|
+
freeze_without_memoizable
|
22
|
+
end
|
23
|
+
|
24
|
+
def memoize_all
|
25
|
+
prime_cache ".*"
|
26
|
+
end
|
27
|
+
|
28
|
+
def unmemoize_all
|
29
|
+
flush_cache ".*"
|
30
|
+
end
|
31
|
+
|
32
|
+
def prime_cache(*syms)
|
33
|
+
syms.each do |sym|
|
34
|
+
methods.each do |m|
|
35
|
+
if m.to_s =~ /^_unmemoized_(#{sym})/
|
36
|
+
if method(m).arity == 0
|
37
|
+
__send__($1)
|
38
|
+
else
|
39
|
+
ivar = ActiveSupport::Memoizable.memoized_ivar_for($1)
|
40
|
+
instance_variable_set(ivar, {})
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def flush_cache(*syms)
|
48
|
+
syms.each do |sym|
|
49
|
+
(methods + private_methods + protected_methods).each do |m|
|
50
|
+
if m.to_s =~ /^_unmemoized_(#{sym.to_s.gsub(/\?\Z/, '\?')})/
|
51
|
+
ivar = ActiveSupport::Memoizable.memoized_ivar_for($1)
|
52
|
+
instance_variable_get(ivar).clear if instance_variable_defined?(ivar)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def memoize(*symbols)
|
60
|
+
symbols.each do |symbol|
|
61
|
+
original_method = :"_unmemoized_#{symbol}"
|
62
|
+
memoized_ivar = ActiveSupport::Memoizable.memoized_ivar_for(symbol)
|
63
|
+
|
64
|
+
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
65
|
+
include InstanceMethods # include InstanceMethods
|
66
|
+
#
|
67
|
+
if method_defined?(:#{original_method}) # if method_defined?(:_unmemoized_mime_type)
|
68
|
+
raise "Already memoized #{symbol}" # raise "Already memoized mime_type"
|
69
|
+
end # end
|
70
|
+
alias #{original_method} #{symbol} # alias _unmemoized_mime_type mime_type
|
71
|
+
#
|
72
|
+
if instance_method(:#{symbol}).arity == 0 # if instance_method(:mime_type).arity == 0
|
73
|
+
def #{symbol}(reload = false) # def mime_type(reload = false)
|
74
|
+
if reload || !defined?(#{memoized_ivar}) || #{memoized_ivar}.empty? # if reload || !defined?(@_memoized_mime_type) || @_memoized_mime_type.empty?
|
75
|
+
#{memoized_ivar} = [#{original_method}] # @_memoized_mime_type = [_unmemoized_mime_type]
|
76
|
+
end # end
|
77
|
+
#{memoized_ivar}[0] # @_memoized_mime_type[0]
|
78
|
+
end # end
|
79
|
+
else # else
|
80
|
+
def #{symbol}(*args) # def mime_type(*args)
|
81
|
+
#{memoized_ivar} ||= {} unless frozen? # @_memoized_mime_type ||= {} unless frozen?
|
82
|
+
args_length = method(:#{original_method}).arity # args_length = method(:_unmemoized_mime_type).arity
|
83
|
+
if args.length == args_length + 1 && # if args.length == args_length + 1 &&
|
84
|
+
(args.last == true || args.last == :reload) # (args.last == true || args.last == :reload)
|
85
|
+
reload = args.pop # reload = args.pop
|
86
|
+
end # end
|
87
|
+
#
|
88
|
+
if defined?(#{memoized_ivar}) && #{memoized_ivar} # if defined?(@_memoized_mime_type) && @_memoized_mime_type
|
89
|
+
if !reload && #{memoized_ivar}.has_key?(args) # if !reload && @_memoized_mime_type.has_key?(args)
|
90
|
+
#{memoized_ivar}[args] # @_memoized_mime_type[args]
|
91
|
+
elsif #{memoized_ivar} # elsif @_memoized_mime_type
|
92
|
+
#{memoized_ivar}[args] = #{original_method}(*args) # @_memoized_mime_type[args] = _unmemoized_mime_type(*args)
|
93
|
+
end # end
|
94
|
+
else # else
|
95
|
+
#{original_method}(*args) # _unmemoized_mime_type(*args)
|
96
|
+
end # end
|
97
|
+
end # end
|
98
|
+
end # end
|
99
|
+
#
|
100
|
+
if private_method_defined?(#{original_method.inspect}) # if private_method_defined?(:_unmemoized_mime_type)
|
101
|
+
private #{symbol.inspect} # private :mime_type
|
102
|
+
elsif protected_method_defined?(#{original_method.inspect}) # elsif protected_method_defined?(:_unmemoized_mime_type)
|
103
|
+
protected #{symbol.inspect} # protected :mime_type
|
104
|
+
end # end
|
105
|
+
EOS
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/kpi.rb
CHANGED
@@ -3,10 +3,11 @@ require 'array/extract_options'
|
|
3
3
|
module KPI
|
4
4
|
require 'engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
|
5
5
|
require 'kpi/18compatibility' if RUBY_VERSION < '1.9'
|
6
|
-
|
6
|
+
require 'kpi/memoizable'
|
7
|
+
|
7
8
|
require File.join(File.dirname(__FILE__), '..', 'app/models/kpi/entry')
|
8
9
|
require File.join(File.dirname(__FILE__), '..', 'app/models/kpi/report/dynamic_definitions')
|
9
10
|
require File.join(File.dirname(__FILE__), '..', 'app/models/kpi/report/suppress_memoization')
|
10
11
|
require File.join(File.dirname(__FILE__), '..', 'app/models/kpi/report')
|
11
12
|
require File.join(File.dirname(__FILE__), '..', 'app/models/kpi/merged_report')
|
12
|
-
end
|
13
|
+
end
|
metadata
CHANGED
@@ -1,122 +1,72 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: kpi
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.7.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 6
|
9
|
-
- 0
|
10
|
-
version: 0.6.0
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Artur Roszczyk
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-12-03 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: actionmailer
|
23
|
-
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
24
17
|
none: false
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
segments:
|
30
|
-
- 2
|
31
|
-
- 3
|
32
|
-
version: "2.3"
|
33
|
-
prerelease: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.3'
|
34
22
|
type: :runtime
|
35
|
-
|
36
|
-
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
37
31
|
name: activesupport
|
38
|
-
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
39
33
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
44
|
-
segments:
|
45
|
-
- 2
|
46
|
-
- 3
|
47
|
-
version: "2.3"
|
48
|
-
prerelease: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '2.3'
|
49
38
|
type: :runtime
|
50
|
-
requirement: *id002
|
51
|
-
- !ruby/object:Gem::Dependency
|
52
|
-
name: minitest
|
53
|
-
version_requirements: &id003 !ruby/object:Gem::Requirement
|
54
|
-
none: false
|
55
|
-
requirements:
|
56
|
-
- - ">="
|
57
|
-
- !ruby/object:Gem::Version
|
58
|
-
hash: 3
|
59
|
-
segments:
|
60
|
-
- 0
|
61
|
-
version: "0"
|
62
39
|
prerelease: false
|
63
|
-
|
64
|
-
requirement: *id003
|
65
|
-
- !ruby/object:Gem::Dependency
|
66
|
-
name: bundler
|
67
|
-
version_requirements: &id004 !ruby/object:Gem::Requirement
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
41
|
none: false
|
69
|
-
requirements:
|
70
|
-
- -
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
|
73
|
-
|
74
|
-
- 1
|
75
|
-
- 0
|
76
|
-
version: "1.0"
|
77
|
-
prerelease: false
|
78
|
-
type: :development
|
79
|
-
requirement: *id004
|
80
|
-
- !ruby/object:Gem::Dependency
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '2.3'
|
46
|
+
- !ruby/object:Gem::Dependency
|
81
47
|
name: jeweler
|
82
|
-
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
83
49
|
none: false
|
84
|
-
requirements:
|
85
|
-
- -
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
|
88
|
-
segments:
|
89
|
-
- 1
|
90
|
-
- 5
|
91
|
-
- 2
|
92
|
-
version: 1.5.2
|
93
|
-
prerelease: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
94
54
|
type: :development
|
95
|
-
requirement: *id005
|
96
|
-
- !ruby/object:Gem::Dependency
|
97
|
-
name: rcov
|
98
|
-
version_requirements: &id006 !ruby/object:Gem::Requirement
|
99
|
-
none: false
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
hash: 3
|
104
|
-
segments:
|
105
|
-
- 0
|
106
|
-
version: "0"
|
107
55
|
prerelease: false
|
108
|
-
|
109
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
110
62
|
description: This gem helps you to track key indicators in your Rails app.
|
111
63
|
email: artur.roszczyk@gmail.com
|
112
64
|
executables: []
|
113
|
-
|
114
65
|
extensions: []
|
115
|
-
|
116
|
-
extra_rdoc_files:
|
66
|
+
extra_rdoc_files:
|
117
67
|
- LICENSE.txt
|
118
68
|
- README.rdoc
|
119
|
-
files:
|
69
|
+
files:
|
120
70
|
- app/models/kpi/entry.rb
|
121
71
|
- app/models/kpi/merged_report.rb
|
122
72
|
- app/models/kpi/report.rb
|
@@ -128,48 +78,35 @@ files:
|
|
128
78
|
- lib/generators/kpi/kpi_generator.rb
|
129
79
|
- lib/kpi.rb
|
130
80
|
- lib/kpi/18compatibility.rb
|
81
|
+
- lib/kpi/memoizable.rb
|
131
82
|
- LICENSE.txt
|
132
83
|
- README.rdoc
|
133
|
-
- test/test_helper.rb
|
134
|
-
- test/unit/kpi/entry_test.rb
|
135
|
-
- test/unit/kpi/merged_report_test.rb
|
136
|
-
- test/unit/kpi/report_test.rb
|
137
|
-
has_rdoc: true
|
138
84
|
homepage: http://github.com/sevos/kpi
|
139
|
-
licenses:
|
85
|
+
licenses:
|
140
86
|
- MIT
|
141
87
|
post_install_message:
|
142
88
|
rdoc_options: []
|
143
|
-
|
144
|
-
require_paths:
|
89
|
+
require_paths:
|
145
90
|
- lib
|
146
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
147
92
|
none: false
|
148
|
-
requirements:
|
149
|
-
- -
|
150
|
-
- !ruby/object:Gem::Version
|
151
|
-
|
152
|
-
segments:
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
segments:
|
153
98
|
- 0
|
154
|
-
|
155
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
hash: 3682157988565917255
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
156
101
|
none: false
|
157
|
-
requirements:
|
158
|
-
- -
|
159
|
-
- !ruby/object:Gem::Version
|
160
|
-
|
161
|
-
segments:
|
162
|
-
- 0
|
163
|
-
version: "0"
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
164
106
|
requirements: []
|
165
|
-
|
166
107
|
rubyforge_project:
|
167
|
-
rubygems_version: 1.
|
108
|
+
rubygems_version: 1.8.24
|
168
109
|
signing_key:
|
169
110
|
specification_version: 3
|
170
111
|
summary: Key Performance Indicators for Rails 3.x
|
171
|
-
test_files:
|
172
|
-
- test/test_helper.rb
|
173
|
-
- test/unit/kpi/entry_test.rb
|
174
|
-
- test/unit/kpi/merged_report_test.rb
|
175
|
-
- test/unit/kpi/report_test.rb
|
112
|
+
test_files: []
|
data/test/test_helper.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
-
require 'minitest/autorun'
|
4
|
-
|
5
|
-
require 'active_support'
|
6
|
-
require 'action_mailer'
|
7
|
-
require 'kpi'
|
8
|
-
|
9
|
-
# Requires supporting files with custom matchers and macros, etc,
|
10
|
-
# in ./support/ and its subdirectories.
|
11
|
-
# Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
data/test/unit/kpi/entry_test.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
|
2
|
-
|
3
|
-
describe "KPI::Entry" do
|
4
|
-
it "should require exactly 2 arguments" do
|
5
|
-
assert_raises(ArgumentError) { KPI::Entry.new }
|
6
|
-
assert_raises(ArgumentError) { KPI::Entry.new "test" }
|
7
|
-
assert_raises(ArgumentError) { KPI::Entry.new "test", 1, "aaa" }
|
8
|
-
end
|
9
|
-
|
10
|
-
describe "when title and value given" do
|
11
|
-
before { @entry = KPI::Entry.new "name", "value" }
|
12
|
-
|
13
|
-
it "returns name" do
|
14
|
-
assert_equal("name", @entry.name)
|
15
|
-
end
|
16
|
-
|
17
|
-
it "returns value" do
|
18
|
-
assert_equal("value", @entry.value)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "returns nil as description" do
|
22
|
-
assert_nil(@entry.description)
|
23
|
-
end
|
24
|
-
describe "when description given" do
|
25
|
-
before { @entry = KPI::Entry.new "name", "value", :description => "desc" }
|
26
|
-
|
27
|
-
it "returns description" do
|
28
|
-
assert_equal("desc", @entry.description)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
describe "when unit given" do
|
33
|
-
before { @entry = KPI::Entry.new "Income", 1294.23, :unit => "EUR" }
|
34
|
-
|
35
|
-
it "returns description" do
|
36
|
-
assert_equal("EUR", @entry.unit)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "when entry is important" do
|
41
|
-
before { @entry = KPI::Entry.new "Income", 1294.23, :important => true }
|
42
|
-
|
43
|
-
it "returns true" do
|
44
|
-
assert @entry.important
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
describe :important? do
|
49
|
-
describe "when entry is important" do
|
50
|
-
before { @entry = KPI::Entry.new "Income", 1294.23, :important => true }
|
51
|
-
|
52
|
-
it "returns true" do
|
53
|
-
assert @entry.important?
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe "when entry is not important" do
|
58
|
-
before { @entry = KPI::Entry.new "Income", 1294.23 }
|
59
|
-
|
60
|
-
it "returns false" do
|
61
|
-
assert !@entry.important?
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,207 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
|
2
|
-
|
3
|
-
describe "KPI::MergedReport" do
|
4
|
-
|
5
|
-
before do
|
6
|
-
class TestKpi < KPI::Report
|
7
|
-
def initialize return_value = 1
|
8
|
-
super()
|
9
|
-
@return = return_value
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_kpi
|
13
|
-
result "title", @return, :description => "description"
|
14
|
-
end
|
15
|
-
|
16
|
-
def test_kpi_2
|
17
|
-
result "title 2 ", @return*2, :unit => 'EUR', :important => true
|
18
|
-
end
|
19
|
-
end
|
20
|
-
class AnotherReport < KPI::Report
|
21
|
-
def test_kpi
|
22
|
-
result "title", 3, :description => "description"
|
23
|
-
end
|
24
|
-
|
25
|
-
def another_kpi
|
26
|
-
result "another", 5
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
after do
|
32
|
-
Object.send(:remove_const, :TestKpi)
|
33
|
-
Object.send(:remove_const, :AnotherReport)
|
34
|
-
end
|
35
|
-
|
36
|
-
describe "when initializing" do
|
37
|
-
it "should initialize with list of KPI::Report::Base objects and block" do
|
38
|
-
KPI::MergedReport.new(TestKpi.new) {}
|
39
|
-
KPI::MergedReport.new(TestKpi.new, TestKpi.new) {}
|
40
|
-
KPI::MergedReport.new(TestKpi.new,TestKpi.new, TestKpi.new) {}
|
41
|
-
end
|
42
|
-
|
43
|
-
it "should require at least one element when initializing" do
|
44
|
-
assert_raises(ArgumentError) do
|
45
|
-
KPI::MergedReport.new() {}
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should allow objects of the same type when initializing" do
|
50
|
-
KPI::MergedReport.new(TestKpi.new, AnotherReport.new) {}
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should require block when initializing" do
|
54
|
-
assert_raises(Exception) do
|
55
|
-
KPI::MergedReport.new(TestKpi.new)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
describe "when two identical reports given for average" do
|
61
|
-
before do
|
62
|
-
@report1 = TestKpi.new(2)
|
63
|
-
@report2 = TestKpi.new(8)
|
64
|
-
|
65
|
-
@average = KPI::MergedReport.new(@report1, @report2) do |*entries|
|
66
|
-
average = entries.map(&:value).sum / entries.size
|
67
|
-
KPI::Entry.new "Average $$", average, :description => "$$ (average)"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
it "should calculate value using block given in initializer when asking for KPI" do
|
72
|
-
assert_equal 5, @average.test_kpi.value
|
73
|
-
end
|
74
|
-
|
75
|
-
it "should change $$ in title to indicator title" do
|
76
|
-
assert_equal "Average title", @average.test_kpi.name
|
77
|
-
end
|
78
|
-
|
79
|
-
it "should change $$ in description to indicator descripiton" do
|
80
|
-
assert_equal "description (average)", @average.test_kpi.description
|
81
|
-
end
|
82
|
-
|
83
|
-
it "should return nil description when no description" do
|
84
|
-
assert_nil @average.test_kpi_2.description
|
85
|
-
end
|
86
|
-
|
87
|
-
it "should have unit" do
|
88
|
-
assert_equal "EUR", @average.test_kpi_2.unit
|
89
|
-
end
|
90
|
-
|
91
|
-
it "should allow to override unit" do
|
92
|
-
@merged = KPI::MergedReport.new(@report1, @report2) do |*entries|
|
93
|
-
KPI::Entry.new "merged $$", 1, :unit => "$"
|
94
|
-
end
|
95
|
-
assert_equal '$', @merged.test_kpi.unit
|
96
|
-
assert_equal '$', @merged.test_kpi_2.unit
|
97
|
-
end
|
98
|
-
|
99
|
-
it "should pass important flag" do
|
100
|
-
assert @average.test_kpi_2.important?
|
101
|
-
end
|
102
|
-
|
103
|
-
it "should allow to override important flag" do
|
104
|
-
@merged = KPI::MergedReport.new(@report1, @report2) do |*entries|
|
105
|
-
KPI::Entry.new "merged $$", 1, :important => true
|
106
|
-
end
|
107
|
-
assert @merged.test_kpi.important?
|
108
|
-
assert @merged.test_kpi_2.important?
|
109
|
-
end
|
110
|
-
|
111
|
-
describe "entries" do
|
112
|
-
it "should return enumerator with entries" do
|
113
|
-
assert_kind_of Enumerable, @average.entries
|
114
|
-
end
|
115
|
-
|
116
|
-
it "should pack average entries to enumerator" do
|
117
|
-
assert @average.entries.all? { |e| e.instance_of?(KPI::Entry) }
|
118
|
-
end
|
119
|
-
|
120
|
-
it "should have each average entry for each indicator" do
|
121
|
-
assert_equal TestKpi.defined_kpis.size, @average.entries.to_a.size
|
122
|
-
end
|
123
|
-
|
124
|
-
it "should calculate averages for each indicator" do
|
125
|
-
assert_equal [5,10], @average.entries.map(&:value)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
describe :defined_kpis do
|
130
|
-
it "should return KPIs defined by all compounds" do
|
131
|
-
assert_equal TestKpi.defined_kpis, @average.defined_kpis
|
132
|
-
end
|
133
|
-
|
134
|
-
it "should check if defined_kpis return array of symbol" do
|
135
|
-
assert_same true, @average.defined_kpis.map(&:class).uniq === [Symbol]
|
136
|
-
end
|
137
|
-
|
138
|
-
it "should return true when calling test_kpi?" do
|
139
|
-
assert @average.test_kpi?
|
140
|
-
end
|
141
|
-
|
142
|
-
it "should return false when calling non existing method with '?'" do
|
143
|
-
assert !@average.test_kpi_23?
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
describe :title do
|
149
|
-
before do
|
150
|
-
@partial_report = TestKpi.new
|
151
|
-
end
|
152
|
-
|
153
|
-
it "should return title passed in options" do
|
154
|
-
report = KPI::MergedReport.new(@partial_report, :title => "my title") {}
|
155
|
-
assert_equal "my title", report.title
|
156
|
-
end
|
157
|
-
|
158
|
-
it "should return title of first report by default" do
|
159
|
-
report = KPI::MergedReport.new(@partial_report) {}
|
160
|
-
assert_equal @partial_report.title, report.title
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
describe "when different reports given for merge" do
|
165
|
-
before do
|
166
|
-
@report1 = TestKpi.new(2)
|
167
|
-
@report2 = AnotherReport.new
|
168
|
-
end
|
169
|
-
|
170
|
-
describe "when intersection" do
|
171
|
-
before do
|
172
|
-
@merge = KPI::MergedReport.new(@report1, @report2) do |test, another|
|
173
|
-
KPI::Entry.new "$$", {:test => test, :another => another}, :description => '$$'
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
it "should have only common KPI defined" do
|
178
|
-
assert_equal [:test_kpi], @merge.defined_kpis
|
179
|
-
end
|
180
|
-
|
181
|
-
it "should not repospond for not common KPI" do
|
182
|
-
assert_raises(NoMethodError) { @merge.another_kpi }
|
183
|
-
end
|
184
|
-
|
185
|
-
it "should return values for common KPI" do
|
186
|
-
assert_instance_of Hash, @merge.test_kpi.value
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
describe "when conjunction" do
|
191
|
-
before do
|
192
|
-
@merge = KPI::MergedReport.new(@report1, @report2, :mode => :|) do |test, another|
|
193
|
-
merge = {:test => test.try(:value), :another => another.try(:value)}
|
194
|
-
KPI::Entry.new "$$", merge, :description => '$$'
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
it "should have all KPI of both reports" do
|
199
|
-
assert_equal [:test_kpi, :test_kpi_2, :another_kpi], @merge.defined_kpis
|
200
|
-
end
|
201
|
-
|
202
|
-
it "should return KPI" do
|
203
|
-
assert_equal({:test => nil, :another => 5}, @merge.another_kpi.value)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
@@ -1,105 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
|
2
|
-
|
3
|
-
describe "KPI::Report" do
|
4
|
-
before do
|
5
|
-
class TestKpi < KPI::Report
|
6
|
-
def test_kpi
|
7
|
-
return KPI::Entry.new "title", 1, :description => "description"
|
8
|
-
end
|
9
|
-
|
10
|
-
def another_kpi
|
11
|
-
return KPI::Entry.new "another title", 0
|
12
|
-
end
|
13
|
-
end
|
14
|
-
@kpi = TestKpi.new
|
15
|
-
end
|
16
|
-
|
17
|
-
after { Object.send(:remove_const, :TestKpi) }
|
18
|
-
|
19
|
-
it "should define indicators" do
|
20
|
-
assert_equal [:test_kpi, :another_kpi], TestKpi.defined_kpis
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should not define indicator from private method" do
|
24
|
-
class TestKpi
|
25
|
-
private
|
26
|
-
def not_kpi
|
27
|
-
end
|
28
|
-
end
|
29
|
-
assert !TestKpi.defined_kpis.include?(:not_kpi)
|
30
|
-
end
|
31
|
-
|
32
|
-
describe :collect! do
|
33
|
-
it "should collect all KPIs" do
|
34
|
-
assert_equal 2, @kpi.collect!.entries.count
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe :defined_kpis do
|
39
|
-
it "should return KPIs defined by class" do
|
40
|
-
assert_equal TestKpi.defined_kpis, @kpi.defined_kpis
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
describe :entries do
|
45
|
-
it "should return enumerator" do
|
46
|
-
assert @kpi.entries.kind_of?(Enumerable)
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should return enumerator with entries" do
|
50
|
-
assert @kpi.entries.first.kind_of?(KPI::Entry)
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should fill entries with names" do
|
54
|
-
assert_equal ["title", "another title"], @kpi.entries.map(&:name)
|
55
|
-
end
|
56
|
-
|
57
|
-
it "should fill entries with values" do
|
58
|
-
assert_equal [1, 0], @kpi.entries.map(&:value)
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should fill entries with descriptions" do
|
62
|
-
assert_equal ["description", nil], @kpi.entries.map(&:description)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
describe :title do
|
67
|
-
it "should return class name by default" do
|
68
|
-
assert_equal "TestKpi", @kpi.title
|
69
|
-
end
|
70
|
-
|
71
|
-
it "should allow to override title in definition" do
|
72
|
-
class AnotherKpi < KPI::Report
|
73
|
-
def title; "title"; end
|
74
|
-
end
|
75
|
-
@kpi = AnotherKpi.new
|
76
|
-
assert_equal "title", @kpi.title
|
77
|
-
assert !@kpi.defined_kpis.include?(:title), 'report should not have :title KPI'
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should allow to override title in options" do
|
81
|
-
assert_equal "my title", TestKpi.new(:title => "my title").title
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
describe :time do
|
86
|
-
it "should return overriden time" do
|
87
|
-
assert_equal(:time, TestKpi.new(:time => :time).time)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
describe :result do
|
92
|
-
it "creates KPI::Entry" do
|
93
|
-
class TestKpi
|
94
|
-
def super_kpi
|
95
|
-
result "test", 2, :description => "desc"
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
@entry = TestKpi.new.super_kpi
|
100
|
-
assert_equal("test", @entry.name)
|
101
|
-
assert_equal(2, @entry.value)
|
102
|
-
assert_equal("desc", @entry.description)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|