ruby-jmeter 2.13.10 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +1 -1
  5. data/Gemfile +2 -2
  6. data/LICENSE.txt +2 -2
  7. data/README.md +4 -5
  8. data/Rakefile +3 -3
  9. data/examples/{basic_os_process_sampler.rb → OS_process_sampler.rb} +1 -1
  10. data/examples/{basic_assertion_results.rb → assertion_results.rb} +1 -3
  11. data/examples/basic_auth.rb +1 -1
  12. data/examples/{basic_browser_headers.rb → browser_headers.rb} +1 -1
  13. data/examples/{basic_composite_graph.rb → composite_graph.rb} +1 -1
  14. data/examples/{basic_gc_dummy_sampler.rb → dummy_sampler.rb} +1 -3
  15. data/examples/{basic_duration_assertion.rb → duration_assertion.rb} +1 -1
  16. data/examples/etsy_login_browse.rb +1 -4
  17. data/examples/{basic_extract.rb → extract.rb} +1 -1
  18. data/examples/{basic_foreach.rb → foreach_controller.rb} +1 -4
  19. data/examples/{basic_header.rb → header_manager.rb} +2 -3
  20. data/examples/{basic_cache.rb → http_cache_manager.rb} +1 -1
  21. data/examples/{basic_cookies.rb → http_cookie_manager.rb} +1 -1
  22. data/examples/{basic_http_request_defaults.rb → http_request_defaults.rb} +3 -2
  23. data/examples/{basic_post.rb → http_request_post.rb} +1 -5
  24. data/examples/{basic_http_request_with_files.rb → http_request_with_files.rb} +1 -1
  25. data/examples/{basic_query_params.rb → http_request_with_query_params.rb} +1 -1
  26. data/examples/{basic_gc_results.rb → jmeter_plugins_graphs.rb} +1 -2
  27. data/examples/{basic_json_path_assertion.rb → json_path_assertions.rb} +1 -1
  28. data/examples/{basic_json_path_extractor.rb → json_path_extractor.rb} +1 -3
  29. data/examples/{basic_ldap_ext.rb → ldap_sampler.rb} +1 -1
  30. data/examples/{basic_loadosophia.rb → loadosophia.rb} +1 -1
  31. data/examples/{basic_loops.rb → loop_controller.rb} +2 -2
  32. data/examples/{basic_counter.rb → loops_with_counter.rb} +2 -2
  33. data/examples/{basic_perfmon.rb → perfmon.rb} +1 -1
  34. data/examples/real_page_objects.rb +1 -1
  35. data/examples/real_user_objects_github.rb +1 -1
  36. data/examples/regular_expression_extractor.rb +11 -0
  37. data/examples/{basic_assertion.rb → response_assertion.rb} +2 -1
  38. data/examples/{basic_response_time_percentiles_graph.rb → response_time_percentiles_graph.rb} +1 -2
  39. data/examples/{basic_simple_data_writer.rb → simple_data_writer_listener.rb} +1 -1
  40. data/examples/{basic_stepping_thread_group.rb → stepping_thread_group.rb} +1 -3
  41. data/examples/{basic_test_fragment.rb → test_fragment.rb} +1 -1
  42. data/examples/{basic_think_time.rb → think_time.rb} +2 -2
  43. data/examples/{basic_thread_groups.rb → thread_groups.rb} +1 -1
  44. data/examples/{basic_throughput_controller.rb → throughput_controller.rb} +1 -1
  45. data/examples/{basic_throughput_shaping_timer.rb → throughput_shaping_timer.rb} +1 -2
  46. data/examples/{basic_ultimate_thread_group.rb → ultimate_thread_group.rb} +1 -2
  47. data/examples/{basic_user_defined_variables.rb → user_defined_variables.rb} +1 -1
  48. data/examples/{basic_preprocessor_user_parameters.rb → user_parameters.rb} +7 -7
  49. data/lib/ruby-jmeter.rb +13 -8
  50. data/lib/ruby-jmeter/DSL.md +3 -1
  51. data/lib/ruby-jmeter/dsl.rb +11 -615
  52. data/lib/ruby-jmeter/dsl/foreach_controller.rb +0 -2
  53. data/lib/ruby-jmeter/dsl/html_parameter_mask.rb +3 -3
  54. data/lib/ruby-jmeter/dsl/http_request.rb +0 -2
  55. data/lib/ruby-jmeter/dsl/http_request_defaults.rb +0 -1
  56. data/lib/ruby-jmeter/dsl/jms_publisher.rb +2 -0
  57. data/lib/ruby-jmeter/dsl/regular_expression_extractor.rb +1 -3
  58. data/lib/ruby-jmeter/dsl/response_assertion.rb +0 -1
  59. data/lib/ruby-jmeter/dsl/test_fragment.rb +1 -1
  60. data/lib/ruby-jmeter/dsl/user_parameters.rb +3 -1
  61. data/lib/ruby-jmeter/extend/assertions/response_assertion.rb +36 -0
  62. data/lib/ruby-jmeter/extend/config_elements/header_manager.rb +13 -0
  63. data/lib/ruby-jmeter/extend/config_elements/http_cache_manager.rb +11 -0
  64. data/lib/ruby-jmeter/extend/config_elements/http_cookie_manager.rb +11 -0
  65. data/lib/ruby-jmeter/extend/config_elements/http_request_defaults.rb +28 -0
  66. data/lib/ruby-jmeter/extend/config_elements/user_defined_variables.rb +13 -0
  67. data/lib/ruby-jmeter/extend/config_elements/user_parameters.rb +31 -0
  68. data/lib/ruby-jmeter/extend/controllers/foreach_controller.rb +25 -0
  69. data/lib/ruby-jmeter/extend/controllers/loop_controller.rb +11 -0
  70. data/lib/ruby-jmeter/extend/controllers/module_controller.rb +23 -0
  71. data/lib/ruby-jmeter/extend/controllers/throughput_controller.rb +15 -0
  72. data/lib/ruby-jmeter/extend/controllers/transaction_controller.rb +14 -0
  73. data/lib/ruby-jmeter/extend/misc/aliases.rb +21 -0
  74. data/lib/ruby-jmeter/extend/misc/exists.rb +13 -0
  75. data/lib/ruby-jmeter/extend/misc/flood.rb +48 -0
  76. data/lib/ruby-jmeter/extend/misc/with_helpers.rb +27 -0
  77. data/lib/ruby-jmeter/extend/plugins/jmeter_plugins.rb +115 -0
  78. data/lib/ruby-jmeter/extend/processors/extract.rb +28 -0
  79. data/lib/ruby-jmeter/extend/processors/regular_expression_extractor.rb +25 -0
  80. data/lib/ruby-jmeter/extend/samplers/http_request.rb +47 -0
  81. data/lib/ruby-jmeter/extend/samplers/soapxmlrpc_request.rb +9 -0
  82. data/lib/ruby-jmeter/extend/threads/setup_thread_group.rb +18 -0
  83. data/lib/ruby-jmeter/extend/threads/thread_group.rb +19 -0
  84. data/lib/ruby-jmeter/extend/timers/constant_throughput_timer.rb +12 -0
  85. data/lib/ruby-jmeter/extend/timers/random_timer.rb +14 -0
  86. data/lib/ruby-jmeter/helpers/helper.rb +1 -2
  87. data/lib/ruby-jmeter/idl.xml +6 -4
  88. data/lib/ruby-jmeter/version.rb +1 -1
  89. data/ruby-jmeter.gemspec +7 -7
  90. data/spec/constant_throughput_timer_spec.rb +22 -0
  91. data/spec/header_manager_spec.rb +37 -0
  92. data/spec/http_cache_manager_spec.rb +17 -0
  93. data/spec/http_cookie_manager_spec.rb +17 -0
  94. data/spec/http_request_defaults_spec.rb +47 -0
  95. data/spec/http_request_spec.rb +305 -0
  96. data/spec/jmeter_plugins_spec.rb +155 -0
  97. data/spec/json_extractor_spec.rb +19 -0
  98. data/spec/json_path_assertion_spec.rb +28 -0
  99. data/spec/logic_controller_spec.rb +148 -0
  100. data/spec/loop_controller_spec.rb +19 -0
  101. data/spec/module_controller_spec.rb +56 -0
  102. data/spec/regular_expression_extractor_spec.rb +63 -0
  103. data/spec/response_assertion_spec.rb +69 -0
  104. data/spec/setup_thread_group_spec.rb +31 -0
  105. data/spec/thread_group_spec.rb +57 -0
  106. data/spec/throughput_controller_spec.rb +24 -0
  107. data/spec/transaction_controller_spec.rb +30 -0
  108. data/spec/user_defined_variables_spec.rb +22 -0
  109. data/spec/user_parameters_spec.rb +45 -0
  110. data/spec/with_helpers_spec.rb +57 -0
  111. data/spec/xpath_extractor_spec.rb +15 -0
  112. metadata +87 -59
  113. data/examples/basic_flood.rb +0 -12
  114. data/examples/basic_flood_real.rb +0 -7
  115. data/examples/basic_flood_with_csv.rb +0 -16
  116. data/examples/basic_google.rb +0 -8
  117. data/examples/basic_har.json +0 -4252
  118. data/examples/basic_har.rb +0 -34
  119. data/examples/basic_meta_fu.rb +0 -63
  120. data/examples/basic_response_assertion.rb +0 -13
  121. data/examples/basic_run.rb +0 -12
  122. data/examples/basic_testdata.rb +0 -60
  123. data/examples/demo.csv +0 -3
  124. data/examples/real_flood_test.rb +0 -14
  125. data/examples/real_flood_test_data.rb +0 -15
  126. data/examples/real_immi.gov.au_visa.rb +0 -78
  127. data/lib/ruby-jmeter/helpers/jmeter.properties +0 -28
  128. data/spec/dsl_spec.rb +0 -1157
  129. data/spec/stub.rb +0 -31
@@ -1,34 +0,0 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- require 'ruby-jmeter'
3
- require 'recursive-open-struct'
4
- require 'json'
5
- require 'pry-debugger'
6
-
7
- har = RecursiveOpenStruct.new(JSON.parse(File.open('basic_har.json').read), recurse_over_arrays: true)
8
-
9
- test do
10
- cache
11
-
12
- cookies
13
-
14
- header [
15
- { name: 'Accept-Encoding', value: 'gzip,deflate,sdch' },
16
- { name: 'Accept', value: 'text/javascript, text/html, application/xml, text/xml, */*' }
17
- ]
18
-
19
- threads count: 1 do
20
-
21
- har.log.entries.collect {|entry| entry.pageref }.uniq.each do |page|
22
-
23
- transaction name: page do
24
- har.log.entries.select {|request| request.pageref == page }.each do |entry|
25
- next unless entry.request.url =~ /http/
26
- params = entry.request.postData && entry.request.postData.params.collect {|param| [param.name, param.value] }.flatten
27
- self.send entry.request.to_h.values.first.downcase, entry.request.url, fill_in: Hash[*params] do
28
- with_xhr if entry.request.headers.to_s =~ /XMLHttpRequest/
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end.out
@@ -1,63 +0,0 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- require 'ruby-jmeter'
3
-
4
- class Test
5
- def initialize options = {}
6
- @users = options[:users]
7
- @ramp = options[:ramp]
8
- @duration = options[:duration]
9
- @region = options[:region] || 'ap-southeast-2'
10
- @name = options[:name]
11
- end
12
-
13
- def flood domain
14
- @domain = domain
15
- test_plan.grid ENV['FLOOD_IO_KEY'], region: @region, name: @name
16
- end
17
-
18
- def jmeter domain
19
- @domain = domain
20
- test_plan.run path: '/usr/share/jmeter/bin/', gui:true
21
- end
22
-
23
- def test_plan
24
- test do
25
- grab_dsl self
26
- defaults domain: @domain,
27
- protocol: 'http',
28
- image_parser: true,
29
- concurrentDwn: true,
30
- concurrentPool: 4
31
-
32
- cookies
33
-
34
- plan
35
- end
36
- end
37
-
38
- def plan
39
- threads @users, {ramp_time: @ramp, duration: @duration, scheduler: true, continue_forever: true} do
40
- random_timer 5000, 10000
41
-
42
- transaction '01_GET_home_page' do
43
- visit '/'
44
- end
45
- end
46
- end
47
-
48
- def grab_dsl dsl
49
- @dsl = dsl
50
- end
51
-
52
- def method_missing method, *args, &block
53
- @dsl.__send__ method, *args, &block
54
- end
55
- end
56
-
57
- test = Test.new users:10, ramp: 30, duration: 30, name: 'Test Number 1'
58
-
59
- # test locally with JMeter
60
- test.jmeter 'google.com'
61
-
62
- # test distributed with flood
63
- # test.flood 'google.com'
@@ -1,13 +0,0 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- require 'ruby-jmeter'
3
-
4
- test do
5
- threads count: 2 do
6
- transaction name: 'Assertions' do
7
- visit name: 'Altentee', url: 'http://altentee.com/' do
8
- response_assertion contains: 'We test, tune and secure your site'
9
- response_assertion 'not-contains' => 'Something in frames', scope: 'children'
10
- end
11
- end
12
- end
13
- end.run(path: '/usr/share/jmeter-2.13/bin/', gui: true)
@@ -1,12 +0,0 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- require 'ruby-jmeter'
3
-
4
- test do
5
- threads count: 1 do
6
- visit name: 'Home Page', url: 'http://google.com/'
7
- end
8
- end.run(
9
- path: '/usr/share/jmeter/bin/',
10
- debug: true,
11
- properties: '/usr/share/jmeter/bin/jmeter.properties'
12
- )
@@ -1,60 +0,0 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- require 'ruby-jmeter'
3
-
4
- test do
5
- threads 1 do
6
-
7
- # populate ${testdata} array with *all* results from shared data url
8
- # using default match number -1
9
- test_data :postcodes
10
-
11
- # testdata now populated with:
12
- #testdata_1=NSW
13
- #testdata_1_g=1
14
- #testdata_1_g0="NSW"
15
- #testdata_1_g1=NSW
16
- #testdata_2=nsw-sydney-2000
17
- #testdata_2_g=1
18
- #testdata_2_g0="nsw-sydney-2000"
19
- #testdata_2_g1=nsw-sydney-2000
20
- #testdata_matchNr=2
21
-
22
- # visit first column match
23
- visit 'http://example.com/?${testdata_1}'
24
-
25
- # visit second column match
26
- visit 'http://example.com/?${testdata_2}'
27
-
28
- # populate named ${postcodes} array with all results from shared data url
29
- # using specific key, command and host
30
- test_data key: 'postcodes',
31
- command: 'SRANDMEMBER',
32
- host: '54.252.206.143'
33
-
34
- # populate named ${postcode_random} from shared data url
35
- # using random result, match number 0 and override name
36
- test_data :postcodes,
37
- name: 'postcode_random',
38
- match_num: 0
39
-
40
-
41
- # populate named ${postcode} from shared data url
42
- # using exact result, match number 1 and override name
43
- test_data 'postcodes',
44
- name: 'postcode_exact',
45
- regex: '^(\d+)',
46
- match_num: 1
47
-
48
- # populate named ${postcode} from a stubbed data url
49
- # with stub = true and default value 2010
50
- test_data 'postcodes',
51
- name: 'postcode_stub',
52
- regex: '^(\d+)',
53
- match_num: 1,
54
- default: '2010',
55
- stub: true
56
-
57
- debug_sampler
58
- view_results
59
- end
60
- end.run(path: '/usr/share/jmeter-2.13/bin/', gui: true)
data/examples/demo.csv DELETED
@@ -1,3 +0,0 @@
1
- apples
2
- oranges
3
- pears
@@ -1,14 +0,0 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- require 'ruby-jmeter'
3
-
4
- test do
5
- threads count: 10, duration: 180, continue_forever: true do
6
- think_time 5_000
7
- visit name: 'Google Search', url: 'http://google.com'
8
- end
9
- end.flood(
10
- ENV['FLOOD_API_TOKEN'],
11
- name: 'Demo',
12
- privacy_flag: 'public',
13
- grid: 'a3Hf9pIs30DX0pYfitU4AA' # UUID of the target grid
14
- )
@@ -1,15 +0,0 @@
1
- require 'ruby-jmeter'
2
-
3
- test do
4
- threads 1 do
5
- get name: '__testdata', url: 'http://54.252.206.143:8080/SRANDMEMBER/postcodes?type=text' do
6
- extract name: 'postcode', regex: '^.+?"(\d+)"'
7
- end
8
- visit name: 'Search Post Code', url: 'http://google.com/?q=${postcode}'
9
- end
10
- end.flood(
11
- ENV['FLOOD_API_TOKEN'],
12
- name: 'Demo',
13
- privacy_flag: 'public',
14
- region: 'us-west-2' # Region of the target grid
15
- )
@@ -1,78 +0,0 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- require 'ruby-jmeter'
3
-
4
- test do
5
-
6
- defaults domain: 'www.immi.gov.au',
7
- protocol: 'http',
8
- image_parser: true,
9
- concurrentDwn: true,
10
- concurrentPool: 4
11
-
12
- cache
13
-
14
- cookies
15
-
16
- with_user_agent :iphone
17
-
18
- header [
19
- { name: 'Accept-Encoding', value: 'gzip,deflate,sdch' },
20
- { name: 'Accept', value: 'text/javascript, text/html, application/xml, text/xml, */*' }
21
- ]
22
-
23
- threads 1, {
24
- rampup: 1,
25
- scheduler: true,
26
- duration: 300,
27
- continue_forever: true
28
- } do
29
-
30
- random_timer 1000, 5000
31
-
32
- transaction 'visa_wizard' do
33
- visit '/visawizard' do
34
- extract xpath: "//select[@id='Q1']/option/@value", name: 'q1', tolerant: true
35
- end
36
- end
37
- # ${__Random(1,${q1_matchNr},n)}
38
- # $__V{q1_${n}}
39
- # $__V{q1_${${__Random(1,${q1_matchNr},)}}}
40
-
41
-
42
- debug_sampler
43
-
44
- transaction 'visa_questions' do
45
- # get '/ecp_new/assess/get?Q1=TRA&Q2=UK&Q3=38&Q4=TRAN&Q5=UK' do
46
- # with_xhr
47
- # assert contains: 'p,'
48
- # extract regex: '(INF\d+)', name: 'answer'
49
- # end
50
- get '/ecp_new/assess/get',
51
- fill_in: {
52
- 'Q1' => '${q1_2}',
53
- 'Q2' => 'UK',
54
- 'Q3' => '38',
55
- 'Q4' => 'TRAN',
56
- 'Q5' => 'UK'
57
- } do
58
- with_xhr
59
- assert contains: 'p,'
60
- extract regex: '(INF\d+)', name: 'answer'
61
- end
62
- end
63
-
64
- transaction 'visa_answer' do
65
- get '/visawizard/inf/${answer}'
66
- end
67
-
68
- view_results
69
-
70
- log filename: '/var/log/flood/custom.log', error_logging: true
71
-
72
- end
73
- end.flood(
74
- ENV['FLOOD_API_TOKEN'],
75
- name: 'Demo',
76
- privacy_flag: 'public',
77
- region: 'us-west-2' # Region of the target grid
78
- )
@@ -1,28 +0,0 @@
1
- jmeter.save.saveservice.output_format=csv
2
- jmeter.save.saveservice.data_type=false
3
- jmeter.save.saveservice.label=true
4
- jmeter.save.saveservice.response_code=true
5
- jmeter.save.saveservice.response_data=false
6
- jmeter.save.saveservice.response_data.on_error=false
7
- jmeter.save.saveservice.response_message=false
8
- jmeter.save.saveservice.successful=true
9
- jmeter.save.saveservice.thread_name=true
10
- jmeter.save.saveservice.time=true
11
- jmeter.save.saveservice.subresults=false
12
- jmeter.save.saveservice.assertions=false
13
- jmeter.save.saveservice.latency=true
14
- jmeter.save.saveservice.samplerData=false
15
- jmeter.save.saveservice.responseHeaders=false
16
- jmeter.save.saveservice.requestHeaders=false
17
- jmeter.save.saveservice.encoding=false
18
- jmeter.save.saveservice.bytes=true
19
- jmeter.save.saveservice.url=false
20
- jmeter.save.saveservice.filename=false
21
- jmeter.save.saveservice.hostname=false
22
- jmeter.save.saveservice.thread_counts=true
23
- jmeter.save.saveservice.sample_count=true
24
- jmeter.save.saveservice.idle_time=false
25
- jmeter.save.saveservice.timestamp_format=ms
26
- jmeter.save.saveservice.default_delimiter=|
27
- jmeter.save.saveservice.print_field_names=false
28
- sample_variables=uuid
data/spec/dsl_spec.rb DELETED
@@ -1,1157 +0,0 @@
1
- require 'spec_helper'
2
- require 'pry'
3
-
4
- describe 'DSL' do
5
- describe 'aliased DSL methods' do
6
- it "test plan should respond to aliased methods" do
7
- test {}.should respond_to :variables
8
- test {}.should respond_to :defaults
9
- test {}.should respond_to :cookies
10
- test {}.should respond_to :cache
11
- test {}.should respond_to :header
12
- test {}.should respond_to :auth
13
- end
14
- end
15
-
16
- describe 'write to stdout and file' do
17
- it "should output a test plan to stdout" do
18
- $stdout.should_receive(:puts).with(/jmeterTestPlan/i)
19
- test do
20
- end.out
21
- end
22
-
23
- it 'should output a test plan to jmx file' do
24
- file = double('file')
25
- File.should_receive(:open).with('jmeter.jmx', 'w').and_yield(file)
26
- file.should_receive(:write).with(/jmeterTestPlan/i)
27
- test do
28
- end.jmx
29
- end
30
- end
31
-
32
- describe 'user agent' do
33
- let(:doc) do
34
- test do
35
- with_user_agent :chrome
36
- threads
37
- end.to_doc
38
- end
39
-
40
- let(:fragment) { doc.search('//HeaderManager').first }
41
-
42
- it 'should match on user_agent' do
43
- fragment.search(".//stringProp[@name='Header.name']").text.should == 'User-Agent'
44
- fragment.search(".//stringProp[@name='Header.value']").text.should ==
45
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5'
46
- end
47
- end
48
-
49
- describe 'http request defaults' do
50
- let(:doc) do
51
- test do
52
- defaults domain: 'example.com',
53
- protocol: 'https',
54
- implementation: 'HttpClient3.1',
55
- download_resources: true,
56
- use_concurrent_pool: 5,
57
- urls_must_match: 'http.+?example.com'
58
- threads do
59
- visit url: "/"
60
- end
61
- end.to_doc
62
- end
63
-
64
- let(:config_fragment) { doc.search('//ConfigTestElement').first }
65
- let(:sampler_fragment) { doc.search('//HTTPSamplerProxy').first }
66
-
67
- it 'should match on implementation' do
68
- sampler_fragment.search(".//stringProp[@name='HTTPSampler.implementation']").text.should == ''
69
- end
70
-
71
- it 'should match on defaults' do
72
- config_fragment.search(".//stringProp[@name='HTTPSampler.domain']").text.should == 'example.com'
73
- config_fragment.search(".//stringProp[@name='HTTPSampler.protocol']").text.should == 'https'
74
- config_fragment.search(".//stringProp[@name='HTTPSampler.implementation']").text.should == 'HttpClient3.1'
75
- config_fragment.search(".//boolProp[@name='HTTPSampler.image_parser']").text.should == 'true'
76
- config_fragment.search(".//boolProp[@name='HTTPSampler.concurrentDwn']").text.should == 'true'
77
- config_fragment.search(".//stringProp[@name='HTTPSampler.concurrentPool']").text.should == '5'
78
- config_fragment.search(".//stringProp[@name='HTTPSampler.embedded_url_re']").text.should == 'http.+?example.com'
79
- end
80
- end
81
-
82
- describe 'disabled elements' do
83
- let(:doc) do
84
- test do
85
- header name: 'Accept', value: '*', enabled: false
86
- end.to_doc
87
- end
88
-
89
- let(:fragment) { doc.search('//HeaderManager') }
90
-
91
- it 'should be disabled' do
92
- fragment.first.attributes['enabled'].value.should == 'false'
93
- end
94
- end
95
-
96
- describe 'header manager' do
97
- let(:doc) do
98
- test do
99
- header name: 'Accept', value: '*'
100
- end.to_doc
101
- end
102
-
103
- let(:fragment) { doc.search('//HeaderManager').first }
104
-
105
- it 'should match on accept' do
106
- fragment.search(".//stringProp[@name='Header.name']").text.should == 'Accept'
107
- fragment.search(".//stringProp[@name='Header.value']").text.should == '*'
108
- end
109
- end
110
-
111
- describe 'header manager multiple values' do
112
- let(:doc) do
113
- test do
114
- header [ { name: 'Accept', value: '1' }, { name: 'Accept', value: '2' }]
115
- end.to_doc
116
- end
117
-
118
- let(:fragment) { doc.search('//HeaderManager') }
119
-
120
-
121
- it 'should match on accept for fragment_first' do
122
- fragment.search(".//stringProp[@name='Header.name']").first.text.should == 'Accept'
123
- fragment.search(".//stringProp[@name='Header.value']").first.text.should == '1'
124
- end
125
-
126
- it 'should match on accept for fragment_last' do
127
- fragment.search(".//stringProp[@name='Header.name']").last.text.should == 'Accept'
128
- fragment.search(".//stringProp[@name='Header.value']").last.text.should == '2'
129
- end
130
- end
131
-
132
- describe 'the clear_each_iteration option should be respected' do
133
- let(:doc) do
134
- test do
135
- cache clear_each_iteration: true
136
- cookies clear_each_iteration: true
137
- end.to_doc
138
- end
139
-
140
- let(:cache_fragment) { doc.search("//CacheManager") }
141
- let(:cookies_fragment) { doc.search("//CookieManager") }
142
-
143
- it 'should match on clearEachIteration' do
144
- cache_fragment.search(".//boolProp[@name='clearEachIteration']").first.text.should == 'true'
145
- cookies_fragment.search(".//boolProp[@name='CookieManager.clearEachIteration']").first.text.should == 'true'
146
- end
147
- end
148
-
149
- describe 'test plan' do
150
- it 'should allow to take params' do
151
- test_plan = test({"TestPlan.serialize_threadgroups" => "false"}) {}
152
- test_plan.to_doc.search("boolProp[@name='TestPlan.serialize_threadgroups']").text.should == "false"
153
-
154
- test_plan = test({"TestPlan.serialize_threadgroups" => "true"}) {}
155
- test_plan.to_doc.search("boolProp[@name='TestPlan.serialize_threadgroups']").text.should == "true"
156
- end
157
- end
158
-
159
- describe 'thread groups' do
160
- let(:doc) do
161
- test do
162
- threads count: 101, continue_forever: true, duration: 69
163
- end.to_doc
164
- end
165
-
166
- let(:fragment) { doc.search("//ThreadGroup").first }
167
-
168
- it 'should match on num_threads' do
169
- fragment.search(".//stringProp[@name='ThreadGroup.num_threads']").text.should == '101'
170
- end
171
-
172
- it 'should match on scheduler' do
173
- fragment.search(".//boolProp[@name='ThreadGroup.scheduler']").text.should == 'true'
174
- end
175
-
176
- it 'should match on continue_forever' do
177
- fragment.search(".//boolProp[@name='LoopController.continue_forever']").text.should == 'true'
178
- end
179
-
180
- it 'should match on loops' do
181
- fragment.search(".//intProp[@name='LoopController.loops']").text.should == '-1'
182
- end
183
-
184
- it 'should match on duration' do
185
- fragment.search(".//stringProp[@name='ThreadGroup.duration']").text.should == '69'
186
- end
187
- end
188
-
189
- describe 'setup thread groups' do
190
- let(:doc) do
191
- test do
192
- setup_thread_group count: 101, continue_forever: true, duration: 69
193
- end.to_doc
194
- end
195
-
196
- let(:fragment) { doc.search("//SetupThreadGroup").first }
197
-
198
- it 'should match on num_threads' do
199
- fragment.search(".//stringProp[@name='ThreadGroup.num_threads']").text.should == '101'
200
- end
201
-
202
- it 'should match on scheduler' do
203
- fragment.search(".//boolProp[@name='ThreadGroup.scheduler']").text.should == 'true'
204
- end
205
-
206
- it 'should match on continue_forever' do
207
- fragment.search(".//boolProp[@name='LoopController.continue_forever']").text.should == 'true'
208
- end
209
-
210
- it 'should match on loops' do
211
- fragment.search(".//stringProp[@name='LoopController.loops']").text.should == '-1'
212
- end
213
-
214
- it 'should match on duration' do
215
- fragment.search(".//stringProp[@name='ThreadGroup.duration']").text.should == '69'
216
- end
217
- end
218
-
219
- describe 'stepping thread group' do
220
- let(:doc) do
221
- test do
222
- stepping_thread_group on_sample_error: 'startnextloop', total_threads: 100, initial_delay: 1, start_threads: 2, add_threads: 3, start_every: 4, stop_threads: 5, stop_every: 6, flight_time: 7, rampup: 8
223
- end.to_doc
224
- end
225
-
226
- let(:fragment) { doc.search("//kg.apc.jmeter.threads.SteppingThreadGroup").first }
227
- it 'should match on on_sample_error' do
228
- fragment.search(".//stringProp[@name='ThreadGroup.on_sample_error']").text.should == 'startnextloop'
229
- end
230
-
231
- it 'should match on total_threads' do
232
- fragment.search(".//stringProp[@name='ThreadGroup.num_threads']").text.should == '100'
233
- end
234
-
235
- it 'should match on initial_delay' do
236
- fragment.search(".//stringProp[@name='Threads initial delay']").text.should == '1'
237
- end
238
-
239
- it 'should match on start_threads' do
240
- fragment.search(".//stringProp[@name='Start users count']").text.should == '2'
241
- end
242
-
243
- it 'should match on add_threads' do
244
- fragment.search(".//stringProp[@name='Start users count burst']").text.should == '3'
245
- end
246
-
247
- it 'should match on start_every' do
248
- fragment.search(".//stringProp[@name='Start users period']").text.should == '4'
249
- end
250
-
251
- it 'should match on stop_threads' do
252
- fragment.search(".//stringProp[@name='Stop users count']").text.should == '5'
253
- end
254
-
255
- it 'should match on stop_every' do
256
- fragment.search(".//stringProp[@name='Stop users period']").text.should == '6'
257
- end
258
-
259
- it 'should match on flight_time' do
260
- fragment.search(".//stringProp[@name='flighttime']").text.should == '7'
261
- end
262
-
263
- it 'should match on rampup' do
264
- fragment.search(".//stringProp[@name='rampUp']").text.should == '8'
265
- end
266
- end
267
-
268
- describe 'thread groups old syntax' do
269
- let(:doc) do
270
- test do
271
- threads 101, continue_forever: true, duration: 69
272
- end.to_doc
273
- end
274
-
275
- let(:fragment) { doc.search("//ThreadGroup").first }
276
-
277
- it 'should match on num_threads' do
278
- fragment.search(".//stringProp[@name='ThreadGroup.num_threads']").text.should == '101'
279
- end
280
-
281
- it 'should match on continue_forever' do
282
- fragment.search(".//boolProp[@name='LoopController.continue_forever']").text.should == 'true'
283
- end
284
-
285
- it 'should match on loops' do
286
- fragment.search(".//intProp[@name='LoopController.loops']").text.should == '-1'
287
- end
288
-
289
- it 'should match on duration' do
290
- fragment.search(".//stringProp[@name='ThreadGroup.duration']").text.should == '69'
291
- end
292
- end
293
-
294
- describe 'transaction controller' do
295
- let(:doc) do
296
- test do
297
- threads do
298
- transaction name: "TC_01", parent: false, include_timers: true
299
- transaction name: "TC_02", parent: true, include_timers: false
300
- end
301
- end.to_doc
302
- end
303
-
304
- let(:fragment) { doc.search("//TransactionController") }
305
-
306
- it 'should match on parent when false' do
307
- fragment.first.search(".//boolProp[@name='TransactionController.parent']").text.should == 'false'
308
- end
309
-
310
- it 'should match on includeTimers when true' do
311
- fragment.first.search(".//boolProp[@name='TransactionController.includeTimers']").text.should == 'true'
312
- end
313
-
314
- it 'should match on parent when true' do
315
- fragment.last.search(".//boolProp[@name='TransactionController.parent']").text.should == 'true'
316
- end
317
-
318
- it 'should match on includeTimers when false' do
319
- fragment.last.search(".//boolProp[@name='TransactionController.includeTimers']").text.should == 'false'
320
- end
321
- end
322
-
323
- describe 'throughput controller' do
324
- let(:doc) do
325
- test do
326
- threads do
327
- throughput_controller percent: 99 do
328
- transaction name: "TC_01", parent: true, include_timers: true
329
- end
330
- end
331
- end.to_doc
332
- end
333
-
334
- let(:fragment) { doc.search("//ThroughputController").first }
335
-
336
- it 'should match on maxThroughput' do
337
- # puts doc.to_xml indent: 2
338
- fragment.search(".//intProp[@name='ThroughputController.maxThroughput']").text.should == '99'
339
- fragment.search(".//FloatProperty/value").text.should == '99.0'
340
- end
341
-
342
- it 'should match on style' do
343
- fragment.search(".//intProp[@name='ThroughputController.style']").text.should == '1'
344
- end
345
- end
346
-
347
- describe 'visit' do
348
- let(:doc) do
349
- test do
350
- threads do
351
- transaction name: "TC_01", parent: true, include_timers: true do
352
- visit url: "/home?location=melbourne&location=sydney", always_encode: true
353
- end
354
- end
355
- end.to_doc
356
- end
357
-
358
- let(:fragment) { doc.search('//HTTPSamplerProxy').first }
359
-
360
- it 'should match on path' do
361
- fragment.search(".//stringProp[@name='HTTPSampler.path']").text.should == '/home'
362
- end
363
-
364
- context "first argument" do
365
- it 'should match on always_encode' do
366
- fragment.search(".//boolProp[@name='HTTPArgument.always_encode']")[0].text.should == 'true'
367
- end
368
-
369
- it 'should match on query param name: location' do
370
- fragment.search(".//stringProp[@name='Argument.name']")[0].text.should == 'location'
371
- end
372
-
373
- it 'should match on query param value: melbourne' do
374
- fragment.search(".//stringProp[@name='Argument.value']")[0].text.should == 'melbourne'
375
- end
376
- end
377
-
378
- context "second argument" do
379
- it 'should match on always_encode' do
380
- fragment.search(".//boolProp[@name='HTTPArgument.always_encode']")[1].text.should == 'true'
381
- end
382
-
383
- it 'should match on query param name: location' do
384
- fragment.search(".//stringProp[@name='Argument.name']")[1].text.should == 'location'
385
- end
386
-
387
- it 'should match on query param value: sydney' do
388
- fragment.search(".//stringProp[@name='Argument.value']")[1].text.should == 'sydney'
389
- end
390
- end
391
- end
392
-
393
- describe 'visit old syntax' do
394
- let(:doc) do
395
- test do
396
- threads do
397
- visit "/home?location=melbourne", always_encode: true
398
- end
399
- end.to_doc
400
- end
401
-
402
- let(:fragment) { doc.search('//HTTPSamplerProxy').first }
403
-
404
- it 'should match on path' do
405
- fragment.search(".//stringProp[@name='HTTPSampler.path']").text.should == '/home'
406
- end
407
- end
408
-
409
- describe 'visit raw_path' do
410
- let(:doc) do
411
- test do
412
- threads do
413
- transaction name: "TC_02" do
414
- post url: "/home?location=melbourne", raw_path: true
415
- end
416
- end
417
- end.to_doc
418
- end
419
-
420
- let(:fragment) { doc.search('//HTTPSamplerProxy').first }
421
-
422
- it 'should match on path' do
423
- fragment.search(".//stringProp[@name='HTTPSampler.path']").text.should == '/home?location=melbourne'
424
- end
425
- end
426
-
427
- describe 'get_with_parameterized_domain' do
428
- let(:doc) do
429
- test do
430
- threads do
431
- transaction name: "TC_01", parent: true, include_timers: true do
432
- visit url: "/home?location=melbourne", domain: "${custom_domain}"
433
- end
434
- end
435
- end.to_doc
436
- end
437
-
438
- let(:fragment) { doc.search('//HTTPSamplerProxy').first }
439
-
440
- it 'should match on path' do
441
- fragment.search(".//stringProp[@name='HTTPSampler.path']").text.should == '/home'
442
- end
443
-
444
- it 'should match on domain' do
445
- fragment.search(".//stringProp[@name='HTTPSampler.domain']").text.should == '${custom_domain}'
446
- end
447
- end
448
-
449
- describe 'https' do
450
- let(:doc) do
451
- test do
452
- threads do
453
- transaction name: "TC_01", parent: true, include_timers: true do
454
- visit url: "https://example.com"
455
- end
456
- end
457
- end.to_doc
458
- end
459
-
460
- let(:fragment) { doc.search('//HTTPSamplerProxy').first }
461
-
462
- it 'should match on protocol' do
463
- fragment.search(".//stringProp[@name='HTTPSampler.protocol']").text.should == 'https'
464
- end
465
- end
466
-
467
- describe 'user_parameters' do
468
- let(:doc) do
469
- test do
470
- threads do
471
- transaction name: "TC_02", parent: true, include_timers: true do
472
- visit url: "/" do
473
- user_parameters names: ['name1', 'name2'],
474
- thread_values: {
475
- user_1: [
476
- 'value1',
477
- 'value2'
478
- ],
479
-
480
- user_2: [
481
- 'value1',
482
- 'value2'
483
- ]
484
- }
485
- end
486
- end
487
- end
488
- end.to_doc
489
- end
490
-
491
- let(:names) { doc.search("//collectionProp[@name='UserParameters.names']").first }
492
- let(:thread_values) { doc.search("//collectionProp[@name='UserParameters.thread_values']").first }
493
-
494
- it 'should match on names' do
495
- names.search(".//stringProp[@name='name1']").text.should == 'name1'
496
- names.search(".//stringProp[@name='name2']").text.should == 'name2'
497
- end
498
-
499
- it 'should match on thread values' do
500
- thread_values.search(".//stringProp[@name='0']").first.text.should == 'value1'
501
- thread_values.search(".//stringProp[@name='1']").first.text.should == 'value2'
502
- end
503
- end
504
-
505
- describe 'xhr' do
506
- let(:doc) do
507
- test do
508
- threads do
509
- transaction name: "TC_02", parent: true, include_timers: true do
510
- visit url: "/" do
511
- with_xhr
512
- end
513
- end
514
- end
515
- end.to_doc
516
- end
517
-
518
- let(:fragment) { doc.search('//HeaderManager').first }
519
-
520
- it 'should match on XHR' do
521
- fragment.search(".//stringProp[@name='Header.value']").text.should == 'XMLHttpRequest'
522
- end
523
- end
524
-
525
- describe 'gzip' do
526
- let(:doc) do
527
- test do
528
- threads do
529
- transaction name: 'TC_02', parent: true, include_timers: true do
530
- visit url: '/' do
531
- with_gzip
532
- end
533
- end
534
- end
535
- end.to_doc
536
- end
537
-
538
- let(:fragment) { doc.search('//HeaderManager').first }
539
-
540
- it 'should match on Acept Encoding' do
541
- fragment.search(".//stringProp[@name='Header.value']").text.should == 'gzip, deflate'
542
- end
543
- end
544
-
545
- describe 'submit' do
546
- let(:doc) do
547
- test do
548
- threads do
549
- transaction name: 'TC_03', parent: true, include_timers: true do
550
- submit url: "/", fill_in: { username: 'tim', password: 'password' }
551
- end
552
- end
553
- end.to_doc
554
- end
555
-
556
- let(:fragment) { doc.search('//HTTPSamplerProxy').first }
557
-
558
- it 'should match on POST' do
559
- fragment.search(".//stringProp[@name='HTTPSampler.method']").text.should == 'POST'
560
- end
561
-
562
- it 'should have no files' do
563
- fragment.search(".//elementProp[@name='HTTPsampler.Files']").length.should == 0
564
- end
565
- end
566
-
567
- describe 'submit_with_files' do
568
- let(:doc) do
569
- test do
570
- threads do
571
- transaction name: "TC_03", parent: true, include_timers: true do
572
- submit url: "/", fill_in: { username: 'tim', password: 'password' },
573
- files: [{path: '/tmp/foo', paramname: 'fileup', mimetype: 'text/plain'},
574
- {path: '/tmp/bar', paramname: 'otherfileup'}]
575
- end
576
- end
577
- end.to_doc
578
- end
579
-
580
- let(:fragment) { doc.search("//HTTPSamplerProxy/elementProp[@name='HTTPsampler.Files']").first }
581
-
582
- it 'should have two files' do
583
- fragment.search("./collectionProp/elementProp[@elementType='HTTPFileArg']").length.should == 2
584
- end
585
-
586
- it 'should have one empty mimetype' do
587
- fragment.search("./collectionProp/elementProp[@elementType='HTTPFileArg']/stringProp[@name='File.mimetype' and normalize-space(.) = '']").length.should == 1
588
- end
589
- end
590
-
591
- describe 'If' do
592
- let(:doc) do
593
- test do
594
- threads do
595
- If condition: '2>1' do
596
- visit url: "/"
597
- end
598
- end
599
- end.to_doc
600
- end
601
-
602
- let(:fragment) { doc.search("//IfController").first }
603
-
604
- it 'should match on If' do
605
- fragment.search(".//stringProp[@name='IfController.condition']").text.should == '2>1'
606
- end
607
- end
608
-
609
- describe 'exists' do
610
- let(:doc) do
611
- test do
612
- threads do
613
- exists 'apple' do
614
- visit url: "/"
615
- end
616
- end
617
- end.to_doc
618
- end
619
-
620
- let(:fragment) { doc.search("//IfController").first }
621
-
622
- it 'should match on exists' do
623
- fragment.search(".//stringProp[@name='IfController.condition']").text.should == '"${apple}" != "\${apple}"'
624
- end
625
- end
626
-
627
- describe 'While' do
628
- let(:doc) do
629
- test do
630
- threads do
631
- While condition: 'true' do
632
- visit url: "/"
633
- end
634
- end
635
- end.to_doc
636
- end
637
-
638
- let(:fragment) { doc.search('//WhileController').first }
639
-
640
- it 'should match on While' do
641
- fragment.search(".//stringProp[@name='WhileController.condition']").text.should == 'true'
642
- end
643
- end
644
-
645
- describe 'Loop' do
646
- let(:doc) do
647
- test do
648
- threads do
649
- Loop count: 5 do
650
- visit url: "/"
651
- end
652
- end
653
- end.to_doc
654
- end
655
-
656
- let(:fragment) { doc.search('//LoopController').first }
657
-
658
- it 'should match on Loops' do
659
- fragment.search(".//stringProp[@name='LoopController.loops']").text.should == '5'
660
- end
661
- end
662
-
663
- describe 'Counter' do
664
- let(:doc) do
665
- test do
666
- threads do
667
- visit url: "/" do
668
- counter start: 1, per_user: true
669
- end
670
- end
671
- end.to_doc
672
- end
673
-
674
- let(:fragment) { doc.search('//CounterConfig').first }
675
-
676
- it 'should match on 5 Loops' do
677
- fragment.search(".//boolProp[@name='CounterConfig.per_user']").text.should == 'true'
678
- end
679
- end
680
-
681
- describe 'Switch' do
682
- let(:doc) do
683
- test do
684
- threads do
685
- Switch value: 'cat' do
686
- visit url: "/"
687
- end
688
- end
689
- end.to_doc
690
- end
691
-
692
- let(:fragment) { doc.search('//SwitchController').first }
693
-
694
- it 'should match on Switch' do
695
- fragment.search(".//stringProp[@name='SwitchController.value']").text.should == 'cat'
696
- end
697
- end
698
-
699
- describe 'regex extract' do
700
- let(:doc) do
701
- test do
702
- extract regex: 'pattern', name: 'my_regex'
703
- end.to_doc
704
- end
705
-
706
- let(:fragment) { doc.search('//RegexExtractor').first }
707
-
708
- it 'should match on refname' do
709
- fragment.search(".//stringProp[@name='RegexExtractor.refname']").text.should == 'my_regex'
710
- end
711
- end
712
-
713
- describe 'regex extract with variable' do
714
- let(:doc) do
715
- test do
716
- extract regex: 'pattern', name: 'my_regex', variable: 'test'
717
- end.to_doc
718
- end
719
-
720
- let(:fragment) { doc.search('//RegexExtractor').first }
721
-
722
- it 'should match on refname' do
723
- fragment.search(".//stringProp[@name='Scope.variable']").text.should == 'test'
724
- end
725
- end
726
-
727
-
728
- describe 'xpath extract' do
729
- let(:doc) do
730
- test do
731
- extract xpath: '//node', name: 'my_xpath'
732
- end.to_doc
733
- end
734
-
735
- let(:fragment) { doc.search('//XPathExtractor').first }
736
-
737
- it 'should match on refname' do
738
- fragment.search(".//stringProp[@name='XPathExtractor.refname']").text.should == 'my_xpath'
739
- end
740
- end
741
-
742
- describe 'json extract' do
743
- let(:doc) do
744
- test do
745
- extract json: '.test.path', name: 'my_json'
746
- end.to_doc
747
- end
748
-
749
- let(:fragment) { doc.search("//com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor").first }
750
-
751
- it 'should match on json path and var' do
752
- fragment.search(".//stringProp[@name='JSONPATH']").text.should == '.test.path'
753
- fragment.search(".//stringProp[@name='VAR']").text.should == 'my_json'
754
- end
755
- end
756
-
757
- describe 'testdata extract' do
758
- let(:doc) do
759
- test do
760
- test_data 'http://54.252.206.143:8080/SRANDMEMBER/postcodes?type=text'
761
- end.to_doc
762
- end
763
-
764
- let(:fragment) { doc.search('//RegexExtractor').first }
765
-
766
- it 'should match on refname' do
767
- fragment.search(".//stringProp[@name='RegexExtractor.refname']").text.should == 'testdata'
768
- end
769
- end
770
-
771
- describe 'assertions' do
772
- describe 'scope all' do
773
- let(:doc) do
774
- test do
775
- visit '/' do
776
- assert contains: 'Welcome'
777
- end
778
- end.to_doc
779
- end
780
-
781
- let(:fragment) { doc.search("//ResponseAssertion").first }
782
-
783
- it 'should match on match' do
784
- fragment.search(".//stringProp[@name='0']").text.should == 'Welcome'
785
- end
786
-
787
- it 'should match on scope' do
788
- fragment.search(".//stringProp[@name='Assertion.scope']").text.should == 'all'
789
- end
790
-
791
- it 'should match on test_type' do
792
- fragment.search(".//intProp[@name='Assertion.test_type']").text.should == '2'
793
- end
794
- end
795
-
796
- describe 'json assertion' do
797
- let(:doc) do
798
- test do
799
- visit '/' do
800
- assert json: '.key', value: 'value'
801
- end
802
- end.to_doc
803
- end
804
-
805
- let(:fragment) { doc.search('//com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.JSONPathAssertion').first }
806
-
807
- it 'should match on expected value' do
808
- fragment.search(".//stringProp[@name='EXPECTED_VALUE']").text.should == "value"
809
- end
810
-
811
- it 'should match on json path' do
812
- fragment.search(".//stringProp[@name='JSON_PATH']").text.should == ".key"
813
- end
814
-
815
- it 'should have json validation by default' do
816
- fragment.search(".//boolProp[@name='JSONVALIDATION']").text.should == "true"
817
- end
818
- end
819
-
820
- describe 'scope main' do
821
- let(:doc) do
822
- test do
823
- visit '/' do
824
- assert contains: 'Welcome', scope: 'main'
825
- end
826
- end.to_doc
827
- end
828
-
829
- let(:fragment) { doc.search('//ResponseAssertion').first }
830
-
831
- it 'should match on scope' do
832
- fragment.search(".//stringProp[@name='Assertion.scope']").text.should == ""
833
- end
834
- end
835
-
836
- describe 'scope variable' do
837
- let(:doc) do
838
- test do
839
- visit '/' do
840
- assert contains: 'someting', variable: 'some_jmeter_variable'
841
- end
842
- end.to_doc
843
- end
844
-
845
- let(:fragment) { doc.search("//ResponseAssertion").first }
846
-
847
- it 'should match on scope' do
848
- fragment.search(".//stringProp[@name='Assertion.scope']").text.should == "variable"
849
- end
850
-
851
- it 'should match on variable' do
852
- fragment.search(".//stringProp[@name='Scope.variable']").text.should == "some_jmeter_variable"
853
- end
854
- end
855
- end
856
-
857
- describe 'Nested controllers' do
858
- let(:doc) do
859
- test do
860
- Simple name: 'node1.1' do
861
- Simple name: 'node2.1'
862
- Simple name: 'node2.2' do
863
- Simple name: 'node3.1'
864
- end
865
- Simple name: 'node2.3'
866
- end
867
- Simple name: 'node1.2'
868
- end.to_doc
869
- end
870
-
871
- let(:node1_1) { doc.search("//GenericController[@testname='node1.1']").first }
872
- let(:node1_2) { doc.search("//GenericController[@testname='node1.2']").first }
873
-
874
- let(:node2_1) { doc.search("//GenericController[@testname='node2.1']").first }
875
- let(:node2_2) { doc.search("//GenericController[@testname='node2.2']").first }
876
- let(:node2_3) { doc.search("//GenericController[@testname='node2.3']").first }
877
-
878
- let(:node3_1) { doc.search("//GenericController[@testname='node3.1']").first }
879
-
880
- it 'nodes should have hashTree as its parent' do
881
- [node1_1, node1_2, node2_1, node2_2, node2_3, node3_1].each do |node|
882
- node.parent.name.should == 'hashTree'
883
- end
884
- end
885
-
886
- describe 'node3_1' do
887
- it 'parent parent should be node2_2' do
888
- node3_1.parent.should == node2_2.next
889
- end
890
- end
891
-
892
- describe 'node1_2' do
893
- it 'previous non hashTree sibling is node1_1' do
894
- node1_2.previous.previous.should == node1_1
895
- end
896
- end
897
- end
898
-
899
- describe 'raw body containing xml entities' do
900
- let(:doc) do
901
- test do
902
- threads do
903
- post url: 'http://example.com', raw_body: 'username=my_name&password=my_password&email="my name <test@example.com>"'
904
- end
905
- end.to_doc
906
- end
907
-
908
- let(:fragment) { doc.search('//HTTPSamplerProxy').first }
909
-
910
- it 'escape raw_body' do
911
- fragment.search(".//stringProp[@name='Argument.value']").text.should == 'username=my_name&password=my_password&email="my name <test@example.com>"'
912
- end
913
- end
914
-
915
- describe 'constant_throughput_timer' do
916
- let(:doc) do
917
- test do
918
- threads do
919
- constant_throughput_timer value: 60.0
920
- constant_throughput_timer throughput: 70.0
921
- end
922
- end.to_doc
923
- end
924
-
925
- let(:fragment) { doc.search("//ConstantThroughputTimer").first }
926
-
927
- it 'should match on throughput using value' do
928
- fragment.search("//doubleProp/value").first.text.should == '60.0'
929
- end
930
-
931
- it 'should match on throughput using throughput' do
932
- fragment.search("//doubleProp/value").last.text.should == '70.0'
933
- end
934
- end
935
-
936
- describe 'run' do
937
- let(:deflate_properties) {
938
- File.expand_path('../../lib/ruby-jmeter/helpers/jmeter.properties', __FILE__)
939
- }
940
-
941
- it 'pass a properties file' do
942
- Open3.should_receive(:popen2e)
943
- .with('jmeter -n -t jmeter.jmx -j jmeter.log -l jmeter.jtl -q my-jmeter.properties ')
944
-
945
- test do
946
- end.run(properties: 'my-jmeter.properties')
947
- end
948
-
949
- it 'pass an inline property' do
950
- Open3.should_receive(:popen2e)
951
- .with('jmeter -n -t jmeter.jmx -j jmeter.log -l jmeter.jtl -Jjmeter.save.saveservice.output_format=xml ')
952
-
953
- test do
954
- end.run(properties: {"jmeter.save.saveservice.output_format" => "xml"})
955
- end
956
-
957
- it 'pass multiple inline properties' do
958
- Open3.should_receive(:popen2e)
959
- .with('jmeter -n -t jmeter.jmx -j jmeter.log -l jmeter.jtl -Jtlon=uqbar -Jorbis=tertius ')
960
-
961
- test do
962
- end.run(properties: {tlon: "uqbar", orbis: "tertius"})
963
- end
964
-
965
- it 'do not pass a properties file' do
966
- Open3.should_receive(:popen2e)
967
- .with("jmeter -n -t jmeter.jmx -j jmeter.log -l jmeter.jtl -q #{deflate_properties} ")
968
-
969
- test do
970
- end.run
971
- end
972
-
973
- it 'pass a nil properties file' do
974
- Open3.should_receive(:popen2e)
975
- .with('jmeter -n -t jmeter.jmx -j jmeter.log -l jmeter.jtl ')
976
-
977
- test do
978
- end.run(properties: nil)
979
- end
980
-
981
- it 'pass remote hosts' do
982
- Open3.should_receive(:popen2e)
983
- .with("jmeter -n -t jmeter.jmx -j jmeter.log -l jmeter.jtl -R 192.168.1.1,192.168.1.2")
984
-
985
- test do
986
- end.run(properties: nil, remote_hosts: '192.168.1.1,192.168.1.2')
987
- end
988
-
989
- it 'pass remote hosts (Array)' do
990
- Open3.should_receive(:popen2e)
991
- .with('jmeter -n -t jmeter.jmx -j jmeter.log -l jmeter.jtl -R 192.168.1.1,192.168.1.2')
992
-
993
- test do
994
- end.run(properties: nil, remote_hosts: ['192.168.1.1', '192.168.1.2'])
995
- end
996
- end
997
-
998
- describe 'module controllers' do
999
- let(:doc) do
1000
- test name: 'tests' do
1001
- threads 1, name: 'threads' do
1002
- Simple name: 'controller_to_call'
1003
- end
1004
- threads 1 do
1005
- module_controller name: 'modules', node_path: [
1006
- 'WorkBench',
1007
- 'tests',
1008
- 'threads',
1009
- 'controller_to_call'
1010
- ]
1011
- end
1012
- end.to_doc
1013
- end
1014
-
1015
- let(:simple_controller) { doc.search("//GenericController").first }
1016
- let(:test_module) { doc.search("//ModuleController").first }
1017
- let(:nodes) { test_module.search(".//stringProp") }
1018
-
1019
- it 'should have a node path' do
1020
- nodes.length.should == 4
1021
- nodes[0].text.should == 'WorkBench'
1022
- nodes[1].text.should == 'tests'
1023
- nodes[2].text.should == 'threads'
1024
- nodes[3].text.should == 'controller_to_call'
1025
- end
1026
- end
1027
-
1028
- describe 'module controllers with test fragment' do
1029
- let(:doc) do
1030
- test do
1031
- test_fragment name: 'some_test_fragment', enabled: 'false' do
1032
- get name: 'Home Page', url: 'http://google.com'
1033
- end
1034
-
1035
- threads count: 1 do
1036
- module_controller test_fragment: 'WorkBench/TestPlan/some_test_fragment'
1037
- end
1038
- end.to_doc
1039
- end
1040
-
1041
- let(:simple_controller) { doc.search("//GenericController").first }
1042
- let(:test_module) { doc.search("//ModuleController").first }
1043
- let(:nodes) { test_module.search(".//stringProp") }
1044
-
1045
- it 'should have a node path specified by test fragment' do
1046
- nodes.length.should == 3
1047
- nodes[0].text.should == 'WorkBench'
1048
- nodes[1].text.should == 'TestPlan'
1049
- nodes[2].text.should == 'some_test_fragment'
1050
- end
1051
- end
1052
-
1053
- describe 'dummy sampler' do
1054
- let(:doc) do
1055
- test do
1056
- threads do
1057
- dummy_sampler 'dummy sampler name', { RESPONSE_DATA: "Some response data" }
1058
- end
1059
- end.to_doc
1060
- end
1061
-
1062
- let(:fragment) { doc.search("//kg.apc.jmeter.samplers.DummySampler").first }
1063
-
1064
- it 'should match on name' do
1065
- fragment.attributes['testname'].value.should == 'dummy sampler name'
1066
- end
1067
-
1068
- it 'should match on response data' do
1069
- fragment.search("//stringProp[@name='RESPONSE_DATA']").text.should == 'Some response data'
1070
- end
1071
- end
1072
-
1073
- describe 'perfmon collector' do
1074
- let(:doc) do
1075
- test do
1076
- threads do
1077
- perfmon_collector name: 'perfmon collector name',
1078
- nodes:
1079
- [
1080
- {server: '1.1.1.1', port: 4444, metric: 'CPU', parameters: ''},
1081
- {server: '2.2.2.2', port: 4444, metric: 'CPU', parameters: ''}
1082
- ],
1083
- filename: 'perf.jtl',
1084
- xml: false
1085
- end
1086
- end.to_doc
1087
- end
1088
-
1089
- let(:fragment) { doc.search("//kg.apc.jmeter.perfmon.PerfMonCollector").first }
1090
- let(:metric_connections) { fragment.search("//collectionProp[@name='metricConnections']").first }
1091
-
1092
- it 'should match on name' do
1093
- fragment.attributes['testname'].value.should == 'perfmon collector name'
1094
- end
1095
-
1096
- it 'should match on xml flag' do
1097
- fragment.search(".//xml").first.text.should == 'false'
1098
- end
1099
-
1100
- it 'should match on first server ip' do
1101
- metric_connections.search("//stringProp[@name='']").first.text.should == '1.1.1.1'
1102
- end
1103
- end
1104
-
1105
- describe 'redis data set' do
1106
- describe 'random keep' do
1107
- let(:doc) do
1108
- test do
1109
- threads do
1110
- redis_data_set name: 'redis data set name',
1111
- host: 'the_host',
1112
- port: 1234
1113
-
1114
- end
1115
- end.to_doc
1116
- end
1117
-
1118
- let(:fragment) { doc.search("//kg.apc.jmeter.config.redis.RedisDataSet").first }
1119
-
1120
- it 'should have a name' do
1121
- fragment.attributes['testname'].value.should == 'redis data set name'
1122
- end
1123
-
1124
- it 'should be configured for random keep' do
1125
- fragment.search("//intProp[@name='getMode']").text.should == '1'
1126
- end
1127
-
1128
- it 'should point to the host' do
1129
- fragment.search("//stringProp[@name='host']").text.should == 'the_host'
1130
- end
1131
-
1132
- it 'should configure a port' do
1133
- fragment.search("//stringProp[@name='port']").text.should == '1234'
1134
- end
1135
- end
1136
-
1137
- describe 'random remove' do
1138
- let(:doc) do
1139
- test do
1140
- threads do
1141
- redis_data_set remove: true
1142
- end
1143
- end.to_doc
1144
- end
1145
-
1146
- let(:fragment) { doc.search("//kg.apc.jmeter.config.redis.RedisDataSet").first }
1147
-
1148
- it 'should have a default name' do
1149
- fragment.attributes['testname'].value.should == 'Redis Data Set Config'
1150
- end
1151
-
1152
- it 'should be configured for random remove' do
1153
- fragment.search("//intProp[@name='getMode']").text.should == '0'
1154
- end
1155
- end
1156
- end
1157
- end