ruby-jmeter 2.13.10 → 3.0.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.
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