gridinit-jmeter 0.0.1
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/.gitattributes +22 -0
- data/.gitignore +20 -0
- data/.rbenv-version +1 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +18 -0
- data/LICENSE.txt +22 -0
- data/README.md +335 -0
- data/Rakefile +6 -0
- data/examples/basic_assertion.rb +13 -0
- data/examples/basic_auth.rb +11 -0
- data/examples/basic_cache.rb +11 -0
- data/examples/basic_cookies.rb +11 -0
- data/examples/basic_google.rb +8 -0
- data/examples/basic_grid.rb +11 -0
- data/examples/basic_run.rb +12 -0
- data/examples/basic_testplan.jmx +138 -0
- data/examples/basic_testplan.rb +44 -0
- data/examples/basic_think_time.rb +12 -0
- data/gridinit-jmeter.gemspec +19 -0
- data/lib/gridinit-jmeter/auth_manager.rb +28 -0
- data/lib/gridinit-jmeter/cache_manager.rb +22 -0
- data/lib/gridinit-jmeter/cookie_manager.rb +23 -0
- data/lib/gridinit-jmeter/dsl.rb +177 -0
- data/lib/gridinit-jmeter/gaussian_random_timer.rb +17 -0
- data/lib/gridinit-jmeter/http_sampler.rb +68 -0
- data/lib/gridinit-jmeter/regex_extractor.rb +25 -0
- data/lib/gridinit-jmeter/response_assertion.rb +58 -0
- data/lib/gridinit-jmeter/test_plan.rb +22 -0
- data/lib/gridinit-jmeter/thread_group.rb +31 -0
- data/lib/gridinit-jmeter/transaction.rb +20 -0
- data/lib/gridinit-jmeter/user_defined_variable.rb +27 -0
- data/lib/gridinit-jmeter/version.rb +5 -0
- data/lib/gridinit-jmeter.rb +20 -0
- data/spec/dsl_spec.rb +35 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/stub.rb +31 -0
- metadata +85 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require 'gridinit-jmeter'
|
3
|
+
|
4
|
+
base_url = 'http://localhost:4567'
|
5
|
+
endpoint = 'localhost:3000'
|
6
|
+
|
7
|
+
test do
|
8
|
+
|
9
|
+
cache clear_each_iteration: true
|
10
|
+
cookies
|
11
|
+
|
12
|
+
threads 100 do
|
13
|
+
|
14
|
+
random_timer 3000, 3000
|
15
|
+
|
16
|
+
transaction 'First Visit', {parent: true} do
|
17
|
+
visit 'Home Page', "#{base_url}/" do
|
18
|
+
extract 'csrf-token', "content='(.+?)' name='csrf-token'"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
transaction 'Login' do
|
23
|
+
submit 'Submit Form', "#{base_url}/login", {
|
24
|
+
fill_in: {
|
25
|
+
username: 'tim',
|
26
|
+
password: 'password',
|
27
|
+
'csrf-token' => '${csrf-token}'
|
28
|
+
}
|
29
|
+
}
|
30
|
+
think_time 1000
|
31
|
+
end
|
32
|
+
|
33
|
+
transaction 'Check Mana' do
|
34
|
+
visit 'Rails Camp' , "#{base_url}/magic" do
|
35
|
+
assert "contains", "magic"
|
36
|
+
assert "not-contains", "unicorns"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
# end.jmx
|
43
|
+
# end.run(path: '/usr/share/jmeter/bin/')
|
44
|
+
end.grid '4dy-zJLEIgpYkKe6p6JhSQ', { endpoint: endpoint }
|
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require 'gridinit-jmeter'
|
3
|
+
|
4
|
+
test do
|
5
|
+
threads 100 do
|
6
|
+
think_time 5000,5000
|
7
|
+
transaction 'Google Search' do
|
8
|
+
visit 'Home Page', 'http://google.com/'
|
9
|
+
random_timer 3000
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end.jmx
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'gridinit-jmeter/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "gridinit-jmeter"
|
8
|
+
gem.version = Gridinit::Jmeter::VERSION
|
9
|
+
gem.authors = ["Tim Koopmans"]
|
10
|
+
gem.email = ["support@gridinit.com"]
|
11
|
+
gem.description = %q{This is a Ruby based DSL for writing JMeter test plans}
|
12
|
+
gem.summary = %q{This is a Ruby based DSL for writing JMeter test plans}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Gridinit
|
2
|
+
module Jmeter
|
3
|
+
|
4
|
+
class AuthManager
|
5
|
+
attr_accessor :doc
|
6
|
+
def initialize(params={})
|
7
|
+
@doc = Nokogiri::XML(<<-EOF.strip_heredoc)
|
8
|
+
<AuthManager guiclass="AuthPanel" testclass="AuthManager" testname="HTTP Authorization Manager" enabled="true">
|
9
|
+
<collectionProp name="AuthManager.auth_list">
|
10
|
+
<elementProp name="" elementType="Authorization">
|
11
|
+
<stringProp name="Authorization.url">/</stringProp>
|
12
|
+
<stringProp name="Authorization.username"></stringProp>
|
13
|
+
<stringProp name="Authorization.password"></stringProp>
|
14
|
+
<stringProp name="Authorization.domain"></stringProp>
|
15
|
+
<stringProp name="Authorization.realm"></stringProp>
|
16
|
+
</elementProp>
|
17
|
+
</collectionProp>
|
18
|
+
</AuthManager>
|
19
|
+
EOF
|
20
|
+
params.each do |name, value|
|
21
|
+
node = @doc.children.xpath("//*[contains(@name,\"#{name.to_s}\")]")
|
22
|
+
node.first.content = value unless node.empty?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Gridinit
|
2
|
+
module Jmeter
|
3
|
+
|
4
|
+
class CacheManager
|
5
|
+
attr_accessor :doc
|
6
|
+
def initialize(params={})
|
7
|
+
@doc = Nokogiri::XML(<<-EOF.strip_heredoc)
|
8
|
+
<CacheManager guiclass="CacheManagerGui" testclass="CacheManager" testname="HTTP Cache Manager" enabled="true">
|
9
|
+
<boolProp name="clearEachIteration">#{params[:clear_each_iteration] ? 'true' : 'false'}</boolProp>
|
10
|
+
<boolProp name="useExpires">#{params[:use_expires] ? 'true' : 'false'}</boolProp>
|
11
|
+
</CacheManager>
|
12
|
+
EOF
|
13
|
+
params.delete :clear_each_iteration
|
14
|
+
params.each do |name, value|
|
15
|
+
node = @doc.children.xpath("//*[contains(@name,\"#{name.to_s}\")]")
|
16
|
+
node.first.content = value unless node.empty?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Gridinit
|
2
|
+
module Jmeter
|
3
|
+
|
4
|
+
class CookieManager
|
5
|
+
attr_accessor :doc
|
6
|
+
def initialize(params={})
|
7
|
+
@doc = Nokogiri::XML(<<-EOF.strip_heredoc)
|
8
|
+
<CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true">
|
9
|
+
<collectionProp name="CookieManager.cookies"/>
|
10
|
+
<boolProp name="CookieManager.clearEachIteration">#{params[:clear_each_iteration] ? 'true' : 'false'}</boolProp>
|
11
|
+
<stringProp name="CookieManager.policy">default</stringProp>
|
12
|
+
</CookieManager>
|
13
|
+
EOF
|
14
|
+
params.delete :clear_each_iteration
|
15
|
+
params.each do |name, value|
|
16
|
+
node = @doc.children.xpath("//*[contains(@name,\"#{name.to_s}\")]")
|
17
|
+
node.first.content = value unless node.empty?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
module Gridinit
|
2
|
+
module Jmeter
|
3
|
+
|
4
|
+
class DSL
|
5
|
+
attr_accessor :root
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@root = Nokogiri::XML(<<-EOF.strip_heredoc)
|
9
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
10
|
+
<jmeterTestPlan version="1.2" properties="2.1">
|
11
|
+
<hashTree>
|
12
|
+
</hashTree>
|
13
|
+
</jmeterTestPlan>
|
14
|
+
EOF
|
15
|
+
node = Gridinit::Jmeter::TestPlan.new
|
16
|
+
@root.at_xpath("//jmeterTestPlan/hashTree") << node.doc.children << hash_tree
|
17
|
+
|
18
|
+
variables(
|
19
|
+
name: 'testguid',
|
20
|
+
value: '${__P(testguid,${__time(,)})}',
|
21
|
+
comments: 'The testguid variable is mandatory when running on the Grid.') {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def variables(params={}, &block)
|
25
|
+
node = Gridinit::Jmeter::UserDefinedVariable.new(params)
|
26
|
+
@root.at_xpath(xpath_from(caller)) << node.doc.children << hash_tree
|
27
|
+
self.instance_exec(&block) if block
|
28
|
+
end
|
29
|
+
|
30
|
+
def cookies(params={}, &block)
|
31
|
+
node = Gridinit::Jmeter::CookieManager.new(params)
|
32
|
+
@root.at_xpath(xpath_from(caller)) << node.doc.children << hash_tree
|
33
|
+
self.instance_exec(&block) if block
|
34
|
+
end
|
35
|
+
|
36
|
+
def cache(params={}, &block)
|
37
|
+
node = Gridinit::Jmeter::CacheManager.new(params)
|
38
|
+
@root.at_xpath(xpath_from(caller)) << node.doc.children << hash_tree
|
39
|
+
self.instance_exec(&block) if block
|
40
|
+
end
|
41
|
+
|
42
|
+
def auth(params={}, &block)
|
43
|
+
node = Gridinit::Jmeter::AuthManager.new(params)
|
44
|
+
@root.at_xpath(xpath_from(caller)) << node.doc.children << hash_tree
|
45
|
+
self.instance_exec(&block) if block
|
46
|
+
end
|
47
|
+
|
48
|
+
def threads(num_threads=1, params={}, &block)
|
49
|
+
node = Gridinit::Jmeter::ThreadGroup.new(num_threads, params)
|
50
|
+
@root.at_xpath(xpath_from(caller)) << node.doc.children << hash_tree
|
51
|
+
self.instance_exec(&block) if block
|
52
|
+
end
|
53
|
+
|
54
|
+
def transaction(name="Transaction Contoller", params={}, &block)
|
55
|
+
node = Gridinit::Jmeter::Transaction.new(name, params)
|
56
|
+
@root.at_xpath(xpath_from(caller)) << node.doc.children << hash_tree
|
57
|
+
self.instance_exec(&block) if block
|
58
|
+
end
|
59
|
+
|
60
|
+
def visit(name="HTTP Request", url="", params={}, &block)
|
61
|
+
params[:method] = 'GET'
|
62
|
+
node = Gridinit::Jmeter::HttpSampler.new(name, url, params)
|
63
|
+
@root.at_xpath(xpath_from(caller)) << node.doc.children << hash_tree
|
64
|
+
self.instance_exec(&block) if block
|
65
|
+
end
|
66
|
+
|
67
|
+
def submit(name="HTTP Request", url="", params={}, &block)
|
68
|
+
params[:method] = 'POST'
|
69
|
+
node = Gridinit::Jmeter::HttpSampler.new(name, url, params)
|
70
|
+
@root.at_xpath(xpath_from(caller)) << node.doc.children << hash_tree
|
71
|
+
self.instance_exec(&block) if block
|
72
|
+
end
|
73
|
+
|
74
|
+
alias_method :post, :submit
|
75
|
+
|
76
|
+
def extract(name="", regex="", params={}, &block)
|
77
|
+
node = Gridinit::Jmeter::RegexExtractor.new(name, regex, params)
|
78
|
+
@root.at_xpath(xpath_from(caller)) << node.doc.children << hash_tree
|
79
|
+
self.instance_exec(&block) if block
|
80
|
+
end
|
81
|
+
|
82
|
+
alias_method :web_reg_save_param, :extract
|
83
|
+
|
84
|
+
def random_timer(delay=0, range=0, &block)
|
85
|
+
node = Gridinit::Jmeter::GaussianRandomTimer.new(delay, range)
|
86
|
+
@root.at_xpath(xpath_from(caller)) << node.doc.children << hash_tree
|
87
|
+
self.instance_exec(&block) if block
|
88
|
+
end
|
89
|
+
|
90
|
+
alias_method :think_time, :random_timer
|
91
|
+
|
92
|
+
def assert(match="contains", pattern="", params={}, &block)
|
93
|
+
node = Gridinit::Jmeter::ResponseAssertion.new(match, pattern, params)
|
94
|
+
@root.at_xpath(xpath_from(caller)) << node.doc.children << hash_tree
|
95
|
+
self.instance_exec(&block) if block
|
96
|
+
end
|
97
|
+
|
98
|
+
alias_method :web_reg_find, :assert
|
99
|
+
|
100
|
+
def jmx(params={})
|
101
|
+
file(params)
|
102
|
+
puts doc.to_xml(:indent => 2)
|
103
|
+
logger.info "JMX saved to: #{params[:file]}"
|
104
|
+
end
|
105
|
+
|
106
|
+
def run(params={})
|
107
|
+
file(params)
|
108
|
+
logger.warn "Test executing locally ..."
|
109
|
+
cmd = "#{params[:path]}jmeter -n -t #{params[:file]} -j #{params[:log] ? params[:log] : 'jmeter.log' } -l #{params[:jtl] ? params[:jtl] : 'jmeter.jtl' }"
|
110
|
+
logger.info cmd
|
111
|
+
`#{cmd}`
|
112
|
+
logger.info "Results at: #{params[:jtl] ? params[:jtl] : 'jmeter.jtl'}"
|
113
|
+
end
|
114
|
+
|
115
|
+
def grid(token, params={})
|
116
|
+
file(params)
|
117
|
+
begin
|
118
|
+
response = RestClient.post "http://#{params[:endpoint] ? params[:endpoint] : 'gridinit.com'}/api?token=#{token}", {
|
119
|
+
:name => 'attachment',
|
120
|
+
:attachment => File.new("#{params[:file]}", 'rb'),
|
121
|
+
:multipart => true,
|
122
|
+
:content_type => 'application/octet-stream'
|
123
|
+
}
|
124
|
+
logger.info "Results at: #{JSON.parse(response)["results"]}" if response.code == 200
|
125
|
+
rescue => e
|
126
|
+
logger.fatal "There was an error: #{e.message}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def hash_tree
|
133
|
+
Nokogiri::XML::Node.new("hashTree", @root)
|
134
|
+
end
|
135
|
+
|
136
|
+
def xpath_from(calling_method)
|
137
|
+
case calling_method.grep(/dsl/)[1][/`.*'/][1..-2]
|
138
|
+
when 'threads'
|
139
|
+
'//ThreadGroup[last()]/following-sibling::hashTree'
|
140
|
+
when 'transaction'
|
141
|
+
'//TransactionController[last()]/following-sibling::hashTree'
|
142
|
+
when 'visit'
|
143
|
+
'//HTTPSamplerProxy[last()]/following-sibling::hashTree'
|
144
|
+
when 'submit'
|
145
|
+
'//HTTPSamplerProxy[last()]/following-sibling::hashTree'
|
146
|
+
when 'extract'
|
147
|
+
'//RegexExtractor[last()]/following-sibling::hashTree'
|
148
|
+
when 'random_timer'
|
149
|
+
'//GaussianRandomTimer[last()]/following-sibling::hashTree'
|
150
|
+
else
|
151
|
+
'//TestPlan/following-sibling::hashTree'
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def file(params={})
|
156
|
+
params[:file] ||= 'jmeter.jmx'
|
157
|
+
File.open(params[:file], 'w') { |file| file.write(doc.to_xml(:indent => 2)) }
|
158
|
+
end
|
159
|
+
|
160
|
+
def doc
|
161
|
+
Nokogiri::XML(@root.to_s,&:noblanks)
|
162
|
+
end
|
163
|
+
|
164
|
+
def logger
|
165
|
+
@log ||= Logger.new(STDOUT)
|
166
|
+
@log.level = Logger::DEBUG
|
167
|
+
@log
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def test(&block)
|
176
|
+
Docile.dsl_eval(Gridinit::Jmeter::DSL.new, &block)
|
177
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Gridinit
|
2
|
+
module Jmeter
|
3
|
+
|
4
|
+
class GaussianRandomTimer
|
5
|
+
attr_accessor :doc
|
6
|
+
def initialize(delay, range)
|
7
|
+
@doc = Nokogiri::XML(<<-EOF.strip_heredoc)
|
8
|
+
<GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Think Time" enabled="true">
|
9
|
+
<stringProp name="ConstantTimer.delay">#{delay}</stringProp>
|
10
|
+
<stringProp name="RandomTimer.range">#{range}</stringProp>
|
11
|
+
</GaussianRandomTimer>
|
12
|
+
EOF
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Gridinit
|
2
|
+
module Jmeter
|
3
|
+
|
4
|
+
class HttpSampler
|
5
|
+
attr_accessor :doc
|
6
|
+
def initialize(name, url, params={})
|
7
|
+
@doc = Nokogiri::XML(<<-EOF.strip_heredoc)
|
8
|
+
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="#{name}" enabled="true">
|
9
|
+
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
10
|
+
<collectionProp name="Arguments.arguments"/>
|
11
|
+
</elementProp>
|
12
|
+
<stringProp name="HTTPSampler.domain"></stringProp>
|
13
|
+
<stringProp name="HTTPSampler.port"></stringProp>
|
14
|
+
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
15
|
+
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
16
|
+
<stringProp name="HTTPSampler.protocol"></stringProp>
|
17
|
+
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
18
|
+
<stringProp name="HTTPSampler.path">/</stringProp>
|
19
|
+
<stringProp name="HTTPSampler.method">GET</stringProp>
|
20
|
+
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
21
|
+
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
22
|
+
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
23
|
+
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
24
|
+
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
25
|
+
<boolProp name="HTTPSampler.image_parser">true</boolProp>
|
26
|
+
<boolProp name="HTTPSampler.concurrentDwn">true</boolProp>
|
27
|
+
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
28
|
+
</HTTPSamplerProxy>
|
29
|
+
EOF
|
30
|
+
parse_url(url, params) unless url.empty?
|
31
|
+
fill_in(params) if params[:fill_in]
|
32
|
+
params.each do |name, value|
|
33
|
+
node = @doc.children.xpath("//*[contains(@name,\"#{name.to_s}\")]")
|
34
|
+
node.first.content = value unless node.empty?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_uri(url)
|
39
|
+
URI.parse(url).scheme.nil? ? URI.parse("http://#{url}") : URI.parse(url)
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse_url(url, params)
|
43
|
+
uri = parse_uri(url)
|
44
|
+
params[:domain] = uri.host
|
45
|
+
params[:port] = uri.port
|
46
|
+
params[:path] = uri.path
|
47
|
+
end
|
48
|
+
|
49
|
+
def fill_in(params)
|
50
|
+
params[:fill_in].each do |name, value|
|
51
|
+
@doc.at_xpath('//collectionProp') <<
|
52
|
+
Nokogiri::XML(<<-EOF.strip_heredoc).children
|
53
|
+
<elementProp name="username" elementType="HTTPArgument">
|
54
|
+
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
55
|
+
<stringProp name="Argument.value">#{value}</stringProp>
|
56
|
+
<stringProp name="Argument.metadata">=</stringProp>
|
57
|
+
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
58
|
+
<stringProp name="Argument.name">#{name}</stringProp>
|
59
|
+
</elementProp>
|
60
|
+
EOF
|
61
|
+
end
|
62
|
+
params.delete :fill_in
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Gridinit
|
2
|
+
module Jmeter
|
3
|
+
|
4
|
+
class RegexExtractor
|
5
|
+
attr_accessor :doc
|
6
|
+
def initialize(name, regex, params={})
|
7
|
+
@doc = Nokogiri::XML(<<-EOF.strip_heredoc)
|
8
|
+
<RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor" enabled="true">
|
9
|
+
<stringProp name="RegexExtractor.useHeaders">false</stringProp>
|
10
|
+
<stringProp name="RegexExtractor.refname">#{name}</stringProp>
|
11
|
+
<stringProp name="RegexExtractor.regex">#{CGI.escapeHTML regex}</stringProp>
|
12
|
+
<stringProp name="RegexExtractor.template">$1$</stringProp>
|
13
|
+
<stringProp name="RegexExtractor.default"></stringProp>
|
14
|
+
<stringProp name="RegexExtractor.match_number">0</stringProp>
|
15
|
+
</RegexExtractor>
|
16
|
+
EOF
|
17
|
+
params.each do |name, value|
|
18
|
+
node = @doc.children.xpath("//*[contains(@name,\"#{name.to_s}\")]")
|
19
|
+
node.first.content = value unless node.empty?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Gridinit
|
2
|
+
module Jmeter
|
3
|
+
|
4
|
+
class ResponseAssertion
|
5
|
+
attr_accessor :doc
|
6
|
+
def initialize(match, pattern, params={})
|
7
|
+
@doc = Nokogiri::XML(<<-EOF.strip_heredoc)
|
8
|
+
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true">
|
9
|
+
<collectionProp name="Asserion.test_strings">
|
10
|
+
<stringProp name="#{Time.now.to_i}">#{pattern}</stringProp>
|
11
|
+
</collectionProp>
|
12
|
+
<stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
|
13
|
+
<boolProp name="Assertion.assume_success">false</boolProp>
|
14
|
+
<intProp name="Assertion.test_type">#{test_type(match)}</intProp>
|
15
|
+
</ResponseAssertion>
|
16
|
+
EOF
|
17
|
+
if params[:scope]
|
18
|
+
@doc.at_xpath('//ResponseAssertion') <<
|
19
|
+
Nokogiri::XML(<<-EOF.strip_heredoc).children
|
20
|
+
<stringProp name="Assertion.scope">#{params[:scope]}</stringProp>
|
21
|
+
EOF
|
22
|
+
params.delete [:scope]
|
23
|
+
end
|
24
|
+
params.each do |name, value|
|
25
|
+
node = @doc.children.xpath("//*[contains(@name,\"#{name.to_s}\")]")
|
26
|
+
node.first.content = value unless node.empty?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def test_type(match)
|
33
|
+
case match
|
34
|
+
when 'contains'
|
35
|
+
2
|
36
|
+
when 'not-contains'
|
37
|
+
6
|
38
|
+
when 'matches'
|
39
|
+
1
|
40
|
+
when 'not-matches'
|
41
|
+
5
|
42
|
+
when 'equals'
|
43
|
+
8
|
44
|
+
when 'not-equals'
|
45
|
+
12
|
46
|
+
when 'substring'
|
47
|
+
16
|
48
|
+
when 'not-substring'
|
49
|
+
20
|
50
|
+
else
|
51
|
+
2
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Gridinit
|
2
|
+
module Jmeter
|
3
|
+
|
4
|
+
class TestPlan
|
5
|
+
attr_accessor :doc
|
6
|
+
def initialize
|
7
|
+
@doc = Nokogiri::XML(<<-EOF.strip_heredoc)
|
8
|
+
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
|
9
|
+
<stringProp name="TestPlan.comments"></stringProp>
|
10
|
+
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
11
|
+
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
12
|
+
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
13
|
+
<collectionProp name="Arguments.arguments"/>
|
14
|
+
</elementProp>
|
15
|
+
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
16
|
+
</TestPlan>
|
17
|
+
EOF
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Gridinit
|
2
|
+
module Jmeter
|
3
|
+
|
4
|
+
class ThreadGroup
|
5
|
+
attr_accessor :doc
|
6
|
+
def initialize(num_threads, params={})
|
7
|
+
@doc = Nokogiri::XML(<<-EOF.strip_heredoc)
|
8
|
+
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
|
9
|
+
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
10
|
+
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
11
|
+
<boolProp name="LoopController.continue_forever">false</boolProp>
|
12
|
+
<stringProp name="LoopController.loops">1</stringProp>
|
13
|
+
</elementProp>
|
14
|
+
<stringProp name="ThreadGroup.num_threads">#{num_threads}</stringProp>
|
15
|
+
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
|
16
|
+
<longProp name="ThreadGroup.start_time">1352677419000</longProp>
|
17
|
+
<longProp name="ThreadGroup.end_time">1352677419000</longProp>
|
18
|
+
<boolProp name="ThreadGroup.scheduler">false</boolProp>
|
19
|
+
<stringProp name="ThreadGroup.duration"></stringProp>
|
20
|
+
<stringProp name="ThreadGroup.delay"></stringProp>
|
21
|
+
</ThreadGroup>
|
22
|
+
EOF
|
23
|
+
params.each do |name, value|
|
24
|
+
node = @doc.children.xpath("//*[contains(@name,\"#{name.to_s}\")]")
|
25
|
+
node.first.content = value unless node.empty?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Gridinit
|
2
|
+
module Jmeter
|
3
|
+
|
4
|
+
class Transaction
|
5
|
+
attr_accessor :doc
|
6
|
+
def initialize(name, params={})
|
7
|
+
@doc = Nokogiri::XML(<<-EOF.strip_heredoc)
|
8
|
+
<TransactionController guiclass="TransactionControllerGui" testclass="TransactionController" testname="#{name}" enabled="true">
|
9
|
+
<boolProp name="TransactionController.parent">false</boolProp>
|
10
|
+
</TransactionController>
|
11
|
+
EOF
|
12
|
+
params.each do |name, value|
|
13
|
+
node = @doc.children.xpath("//*[contains(@name,\"#{name.to_s}\")]")
|
14
|
+
node.first.content = value unless node.empty?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Gridinit
|
2
|
+
module Jmeter
|
3
|
+
|
4
|
+
class UserDefinedVariable
|
5
|
+
attr_accessor :doc
|
6
|
+
def initialize(params={})
|
7
|
+
@doc = Nokogiri::XML(<<-EOF.strip_heredoc)
|
8
|
+
<Arguments guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
9
|
+
<collectionProp name="Arguments.arguments">
|
10
|
+
<elementProp name="testguid" elementType="Argument">
|
11
|
+
<stringProp name="Argument.name"></stringProp>
|
12
|
+
<stringProp name="Argument.value"></stringProp>
|
13
|
+
<stringProp name="Argument.metadata">=</stringProp>
|
14
|
+
</elementProp>
|
15
|
+
</collectionProp>
|
16
|
+
<stringProp name="TestPlan.comments"></stringProp>
|
17
|
+
</Arguments>
|
18
|
+
EOF
|
19
|
+
params.each do |name, value|
|
20
|
+
node = @doc.children.xpath("//*[contains(@name,\"#{name.to_s}\")]")
|
21
|
+
node.first.content = value unless node.empty?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'docile'
|
3
|
+
require 'active_support/core_ext'
|
4
|
+
require 'logger/colors'
|
5
|
+
require 'rest_client'
|
6
|
+
require 'cgi'
|
7
|
+
|
8
|
+
require 'gridinit-jmeter/dsl'
|
9
|
+
require 'gridinit-jmeter/version'
|
10
|
+
require 'gridinit-jmeter/test_plan'
|
11
|
+
require 'gridinit-jmeter/auth_manager'
|
12
|
+
require 'gridinit-jmeter/cookie_manager'
|
13
|
+
require 'gridinit-jmeter/cache_manager'
|
14
|
+
require 'gridinit-jmeter/thread_group'
|
15
|
+
require 'gridinit-jmeter/transaction'
|
16
|
+
require 'gridinit-jmeter/http_sampler'
|
17
|
+
require 'gridinit-jmeter/regex_extractor'
|
18
|
+
require 'gridinit-jmeter/user_defined_variable'
|
19
|
+
require 'gridinit-jmeter/gaussian_random_timer'
|
20
|
+
require 'gridinit-jmeter/response_assertion'
|
data/spec/dsl_spec.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "DSL" do
|
4
|
+
|
5
|
+
it "test plan should respond to thread groups" do
|
6
|
+
test {}.should respond_to :threads
|
7
|
+
end
|
8
|
+
|
9
|
+
it "test plan should respond to transactions" do
|
10
|
+
test {}.should respond_to :transaction
|
11
|
+
end
|
12
|
+
|
13
|
+
it "test plan should respond to visit" do
|
14
|
+
test {}.should respond_to :visit
|
15
|
+
end
|
16
|
+
|
17
|
+
it "test plan should respond to submit" do
|
18
|
+
test {}.should respond_to :submit
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should output a test plan to stdout" do
|
22
|
+
$stdout.should_receive(:puts).with(/jmeterTestPlan/i)
|
23
|
+
test do
|
24
|
+
end.jmx
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should output a test plan to jmx file" do
|
28
|
+
file = mock('file')
|
29
|
+
File.should_receive(:open).with("/tmp/jmeter.jmx", "w").and_yield(file)
|
30
|
+
file.should_receive(:write).with(/jmeterTestPlan/i)
|
31
|
+
test do
|
32
|
+
end.jmx
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|