ruby-jmeter 2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. data/.gitattributes +22 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +27 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +333 -0
  7. data/Rakefile +6 -0
  8. data/bin/grid +25 -0
  9. data/examples/basic_assertion.rb +13 -0
  10. data/examples/basic_auth.rb +11 -0
  11. data/examples/basic_cache.rb +11 -0
  12. data/examples/basic_cookies.rb +11 -0
  13. data/examples/basic_extract.rb +10 -0
  14. data/examples/basic_gc_dummy_sampler.rb +10 -0
  15. data/examples/basic_gc_results.rb +23 -0
  16. data/examples/basic_google.rb +8 -0
  17. data/examples/basic_grid.rb +8 -0
  18. data/examples/basic_header.rb +19 -0
  19. data/examples/basic_ldap_ext.rb +16 -0
  20. data/examples/basic_post.rb +15 -0
  21. data/examples/basic_query_params.rb +8 -0
  22. data/examples/basic_think_time.rb +15 -0
  23. data/examples/basic_throughput_controller.rb +14 -0
  24. data/examples/basic_throughput_shaping_timer.rb +21 -0
  25. data/examples/etsy_login_browse.rb +64 -0
  26. data/lib/ruby-jmeter.rb +18 -0
  27. data/lib/ruby-jmeter/DSL.md +237 -0
  28. data/lib/ruby-jmeter/dsl.rb +419 -0
  29. data/lib/ruby-jmeter/dsl/access_log_sampler.rb +32 -0
  30. data/lib/ruby-jmeter/dsl/aggregate_graph.rb +55 -0
  31. data/lib/ruby-jmeter/dsl/aggregate_report.rb +55 -0
  32. data/lib/ruby-jmeter/dsl/ajp13_sampler.rb +41 -0
  33. data/lib/ruby-jmeter/dsl/assertion_results.rb +55 -0
  34. data/lib/ruby-jmeter/dsl/beanshell_assertion.rb +28 -0
  35. data/lib/ruby-jmeter/dsl/beanshell_listener.rb +28 -0
  36. data/lib/ruby-jmeter/dsl/beanshell_postprocessor.rb +28 -0
  37. data/lib/ruby-jmeter/dsl/beanshell_preprocessor.rb +28 -0
  38. data/lib/ruby-jmeter/dsl/beanshell_sampler.rb +28 -0
  39. data/lib/ruby-jmeter/dsl/beanshell_timer.rb +28 -0
  40. data/lib/ruby-jmeter/dsl/bsf_assertion.rb +28 -0
  41. data/lib/ruby-jmeter/dsl/bsf_listener.rb +28 -0
  42. data/lib/ruby-jmeter/dsl/bsf_postprocessor.rb +28 -0
  43. data/lib/ruby-jmeter/dsl/bsf_preprocessor.rb +28 -0
  44. data/lib/ruby-jmeter/dsl/bsf_sampler.rb +28 -0
  45. data/lib/ruby-jmeter/dsl/bsf_timer.rb +28 -0
  46. data/lib/ruby-jmeter/dsl/compare_assertion.rb +27 -0
  47. data/lib/ruby-jmeter/dsl/comparison_assertion_visualizer.rb +55 -0
  48. data/lib/ruby-jmeter/dsl/constant_throughput_timer.rb +30 -0
  49. data/lib/ruby-jmeter/dsl/constant_timer.rb +25 -0
  50. data/lib/ruby-jmeter/dsl/counter.rb +31 -0
  51. data/lib/ruby-jmeter/dsl/cssjquery_extractor.rb +30 -0
  52. data/lib/ruby-jmeter/dsl/csv_data_set_config.rb +32 -0
  53. data/lib/ruby-jmeter/dsl/debug_postprocessor.rb +28 -0
  54. data/lib/ruby-jmeter/dsl/debug_sampler.rb +27 -0
  55. data/lib/ruby-jmeter/dsl/distribution_graphalpha.rb +55 -0
  56. data/lib/ruby-jmeter/dsl/duration_assertion.rb +25 -0
  57. data/lib/ruby-jmeter/dsl/foreach_controller.rb +29 -0
  58. data/lib/ruby-jmeter/dsl/ftp_request.rb +34 -0
  59. data/lib/ruby-jmeter/dsl/ftp_request_defaults.rb +32 -0
  60. data/lib/ruby-jmeter/dsl/gaussian_random_timer.rb +26 -0
  61. data/lib/ruby-jmeter/dsl/generate_summary_results.rb +23 -0
  62. data/lib/ruby-jmeter/dsl/graph_results.rb +55 -0
  63. data/lib/ruby-jmeter/dsl/html_assertion.rb +30 -0
  64. data/lib/ruby-jmeter/dsl/html_link_parser.rb +23 -0
  65. data/lib/ruby-jmeter/dsl/html_parameter_mask.rb +32 -0
  66. data/lib/ruby-jmeter/dsl/http_authorization_manager.rb +33 -0
  67. data/lib/ruby-jmeter/dsl/http_cache_manager.rb +26 -0
  68. data/lib/ruby-jmeter/dsl/http_cookie_manager.rb +27 -0
  69. data/lib/ruby-jmeter/dsl/http_header_manager.rb +30 -0
  70. data/lib/ruby-jmeter/dsl/http_request.rb +41 -0
  71. data/lib/ruby-jmeter/dsl/http_request_defaults.rb +44 -0
  72. data/lib/ruby-jmeter/dsl/http_url_rewriting_modifier.rb +29 -0
  73. data/lib/ruby-jmeter/dsl/if_controller.rb +27 -0
  74. data/lib/ruby-jmeter/dsl/include_controller.rb +25 -0
  75. data/lib/ruby-jmeter/dsl/java_request.rb +69 -0
  76. data/lib/ruby-jmeter/dsl/java_request_defaults.rb +69 -0
  77. data/lib/ruby-jmeter/dsl/jdbc_connection_configuration.rb +37 -0
  78. data/lib/ruby-jmeter/dsl/jdbc_postprocessor.rb +31 -0
  79. data/lib/ruby-jmeter/dsl/jdbc_preprocessor.rb +31 -0
  80. data/lib/ruby-jmeter/dsl/jdbc_request.rb +31 -0
  81. data/lib/ruby-jmeter/dsl/jms_pointtopoint.rb +40 -0
  82. data/lib/ruby-jmeter/dsl/jms_publisher.rb +41 -0
  83. data/lib/ruby-jmeter/dsl/jms_subscriber.rb +35 -0
  84. data/lib/ruby-jmeter/dsl/jsr223_assertion.rb +29 -0
  85. data/lib/ruby-jmeter/dsl/jsr223_listener.rb +29 -0
  86. data/lib/ruby-jmeter/dsl/jsr223_postprocessor.rb +29 -0
  87. data/lib/ruby-jmeter/dsl/jsr223_preprocessor.rb +29 -0
  88. data/lib/ruby-jmeter/dsl/jsr223_sampler.rb +29 -0
  89. data/lib/ruby-jmeter/dsl/jsr223_timer.rb +29 -0
  90. data/lib/ruby-jmeter/dsl/junit_request.rb +37 -0
  91. data/lib/ruby-jmeter/dsl/keystore_configuration.rb +27 -0
  92. data/lib/ruby-jmeter/dsl/ldap_extended_request.rb +42 -0
  93. data/lib/ruby-jmeter/dsl/ldap_extended_request_defaults.rb +42 -0
  94. data/lib/ruby-jmeter/dsl/ldap_request.rb +35 -0
  95. data/lib/ruby-jmeter/dsl/ldap_request_defaults.rb +40 -0
  96. data/lib/ruby-jmeter/dsl/login_config_element.rb +26 -0
  97. data/lib/ruby-jmeter/dsl/loop_controller.rb +26 -0
  98. data/lib/ruby-jmeter/dsl/mail_reader_sampler.rb +37 -0
  99. data/lib/ruby-jmeter/dsl/mailer_visualizer.rb +64 -0
  100. data/lib/ruby-jmeter/dsl/md5hex_assertion.rb +25 -0
  101. data/lib/ruby-jmeter/dsl/module_controller.rb +23 -0
  102. data/lib/ruby-jmeter/dsl/monitor_results.rb +55 -0
  103. data/lib/ruby-jmeter/dsl/once_only_controller.rb +23 -0
  104. data/lib/ruby-jmeter/dsl/os_process_sampler.rb +34 -0
  105. data/lib/ruby-jmeter/dsl/poisson_random_timer.rb +26 -0
  106. data/lib/ruby-jmeter/dsl/random_controller.rb +25 -0
  107. data/lib/ruby-jmeter/dsl/random_order_controller.rb +23 -0
  108. data/lib/ruby-jmeter/dsl/random_variable.rb +30 -0
  109. data/lib/ruby-jmeter/dsl/recording_controller.rb +23 -0
  110. data/lib/ruby-jmeter/dsl/regex_user_parameters.rb +27 -0
  111. data/lib/ruby-jmeter/dsl/regular_expression_extractor.rb +31 -0
  112. data/lib/ruby-jmeter/dsl/response_assertion.rb +31 -0
  113. data/lib/ruby-jmeter/dsl/response_time_graph.rb +55 -0
  114. data/lib/ruby-jmeter/dsl/result_status_action_handler.rb +25 -0
  115. data/lib/ruby-jmeter/dsl/runtime_controller.rb +25 -0
  116. data/lib/ruby-jmeter/dsl/save_responses_to_a_file.rb +29 -0
  117. data/lib/ruby-jmeter/dsl/simple_config_element.rb +23 -0
  118. data/lib/ruby-jmeter/dsl/simple_controller.rb +23 -0
  119. data/lib/ruby-jmeter/dsl/simple_data_writer.rb +55 -0
  120. data/lib/ruby-jmeter/dsl/smime_assertion.rb +35 -0
  121. data/lib/ruby-jmeter/dsl/smtp_sampler.rb +51 -0
  122. data/lib/ruby-jmeter/dsl/soapxmlrpc_request.rb +33 -0
  123. data/lib/ruby-jmeter/dsl/spline_visualizer.rb +55 -0
  124. data/lib/ruby-jmeter/dsl/summary_report.rb +55 -0
  125. data/lib/ruby-jmeter/dsl/switch_controller.rb +25 -0
  126. data/lib/ruby-jmeter/dsl/synchronizing_timer.rb +25 -0
  127. data/lib/ruby-jmeter/dsl/tcp_sampler.rb +33 -0
  128. data/lib/ruby-jmeter/dsl/tcp_sampler_config.rb +31 -0
  129. data/lib/ruby-jmeter/dsl/test_action.rb +27 -0
  130. data/lib/ruby-jmeter/dsl/test_plan.rb +31 -0
  131. data/lib/ruby-jmeter/dsl/thread_group.rb +36 -0
  132. data/lib/ruby-jmeter/dsl/throughput_controller.rb +32 -0
  133. data/lib/ruby-jmeter/dsl/transaction_controller.rb +26 -0
  134. data/lib/ruby-jmeter/dsl/uniform_random_timer.rb +26 -0
  135. data/lib/ruby-jmeter/dsl/user_defined_variables.rb +32 -0
  136. data/lib/ruby-jmeter/dsl/user_parameters.rb +29 -0
  137. data/lib/ruby-jmeter/dsl/view_results_in_table.rb +55 -0
  138. data/lib/ruby-jmeter/dsl/view_results_tree.rb +55 -0
  139. data/lib/ruby-jmeter/dsl/while_controller.rb +25 -0
  140. data/lib/ruby-jmeter/dsl/xml_assertion.rb +23 -0
  141. data/lib/ruby-jmeter/dsl/xml_schema_assertion.rb +25 -0
  142. data/lib/ruby-jmeter/dsl/xpath_assertion.rb +30 -0
  143. data/lib/ruby-jmeter/dsl/xpath_extractor.rb +30 -0
  144. data/lib/ruby-jmeter/helpers/fallback_content_proxy.rb +54 -0
  145. data/lib/ruby-jmeter/helpers/helper.rb +41 -0
  146. data/lib/ruby-jmeter/helpers/jmeter.properties +28 -0
  147. data/lib/ruby-jmeter/helpers/logger-colors.rb +48 -0
  148. data/lib/ruby-jmeter/helpers/parser.rb +106 -0
  149. data/lib/ruby-jmeter/helpers/strip-heredoc.rb +5 -0
  150. data/lib/ruby-jmeter/helpers/user-agents.rb +27 -0
  151. data/lib/ruby-jmeter/idl.rb +70 -0
  152. data/lib/ruby-jmeter/idl.xml +1513 -0
  153. data/lib/ruby-jmeter/plugins/gc_console_status_logger.rb +14 -0
  154. data/lib/ruby-jmeter/plugins/gc_dummy_sampler.rb +23 -0
  155. data/lib/ruby-jmeter/plugins/gc_latencies_over_time.rb +48 -0
  156. data/lib/ruby-jmeter/plugins/gc_response_codes_per_second.rb +48 -0
  157. data/lib/ruby-jmeter/plugins/gc_response_times_distribution.rb +47 -0
  158. data/lib/ruby-jmeter/plugins/gc_response_times_over_time.rb +48 -0
  159. data/lib/ruby-jmeter/plugins/gc_response_times_percentiles.rb +48 -0
  160. data/lib/ruby-jmeter/plugins/gc_transactions_per_second.rb +48 -0
  161. data/lib/ruby-jmeter/plugins/gc_variable_throughput_timer.rb +26 -0
  162. data/lib/ruby-jmeter/version.rb +3 -0
  163. data/ruby-jmeter.gemspec +22 -0
  164. data/spec/dsl_spec.rb +491 -0
  165. data/spec/spec_helper.rb +10 -0
  166. data/spec/stub.rb +31 -0
  167. metadata +244 -0
@@ -0,0 +1,14 @@
1
+ module RubyJmeter
2
+
3
+ class GCConsoleStatusLogger
4
+ attr_accessor :doc
5
+ include Helper
6
+ def initialize(name, params={})
7
+ @doc = Nokogiri::XML(<<-EOF.strip_heredoc)
8
+ <kg.apc.jmeter.reporters.ConsoleStatusLogger guiclass="kg.apc.jmeter.reporters.ConsoleStatusLoggerGui" testclass="kg.apc.jmeter.reporters.ConsoleStatusLogger" testname="#{name}" enabled="true"/>
9
+ EOF
10
+ update params
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,23 @@
1
+ module RubyJmeter
2
+
3
+ class GCDummySampler
4
+ attr_accessor :doc
5
+ include Helper
6
+ def initialize(name, params={})
7
+ @doc = Nokogiri::XML(<<-EOF.strip_heredoc)
8
+ <kg.apc.jmeter.samplers.DummySampler guiclass="kg.apc.jmeter.samplers.DummySamplerGui" testclass="kg.apc.jmeter.samplers.DummySampler" testname="jp@gc - Dummy Sampler" enabled="true">
9
+ <boolProp name="WAITING">true</boolProp>
10
+ <boolProp name="SUCCESFULL">true</boolProp>
11
+ <stringProp name="RESPONSE_CODE">200</stringProp>
12
+ <stringProp name="RESPONSE_MESSAGE">OK</stringProp>
13
+ <stringProp name="REQUEST_DATA"></stringProp>
14
+ <stringProp name="RESPONSE_DATA"></stringProp>
15
+ <stringProp name="RESPONSE_TIME">0</stringProp>
16
+ <stringProp name="LATENCY">0</stringProp>
17
+ </kg.apc.jmeter.samplers.DummySampler>
18
+ EOF
19
+ update params
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,48 @@
1
+ module RubyJmeter
2
+
3
+ class GCLatenciesOverTime
4
+ attr_accessor :doc
5
+ include Helper
6
+ def initialize(name, params={})
7
+ @doc = Nokogiri::XML(<<-EOF.strip_heredoc)
8
+ <kg.apc.jmeter.vizualizers.CorrectedResultCollector guiclass="kg.apc.jmeter.vizualizers.LatenciesOverTimeGui" testclass="kg.apc.jmeter.vizualizers.CorrectedResultCollector" testname="#{name}" enabled="#{enabled(params)}">
9
+ <boolProp name="ResultCollector.error_logging">false</boolProp>
10
+ <objProp>
11
+ <name>saveConfig</name>
12
+ <value class="SampleSaveConfiguration">
13
+ <time>true</time>
14
+ <latency>true</latency>
15
+ <timestamp>true</timestamp>
16
+ <success>true</success>
17
+ <label>true</label>
18
+ <code>true</code>
19
+ <message>true</message>
20
+ <threadName>true</threadName>
21
+ <dataType>true</dataType>
22
+ <encoding>false</encoding>
23
+ <assertions>true</assertions>
24
+ <subresults>true</subresults>
25
+ <responseData>false</responseData>
26
+ <samplerData>false</samplerData>
27
+ <xml>true</xml>
28
+ <fieldNames>false</fieldNames>
29
+ <responseHeaders>false</responseHeaders>
30
+ <requestHeaders>false</requestHeaders>
31
+ <responseDataOnError>false</responseDataOnError>
32
+ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
33
+ <assertionsResultsToSave>0</assertionsResultsToSave>
34
+ <bytes>true</bytes>
35
+ </value>
36
+ </objProp>
37
+ <stringProp name="filename"></stringProp>
38
+ <longProp name="interval_grouping">500</longProp>
39
+ <boolProp name="graph_aggregated">false</boolProp>
40
+ <stringProp name="include_sample_labels"></stringProp>
41
+ <stringProp name="exclude_sample_labels"></stringProp>
42
+ </kg.apc.jmeter.vizualizers.CorrectedResultCollector>
43
+ EOF
44
+ update params
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,48 @@
1
+ module RubyJmeter
2
+
3
+ class GCResponseCodesPerSecond
4
+ attr_accessor :doc
5
+ include Helper
6
+ def initialize(name, params={})
7
+ @doc = Nokogiri::XML(<<-EOF.strip_heredoc)
8
+ <kg.apc.jmeter.vizualizers.CorrectedResultCollector guiclass="kg.apc.jmeter.vizualizers.ResponseCodesPerSecondGui" testclass="kg.apc.jmeter.vizualizers.CorrectedResultCollector" testname="#{name}" enabled="#{enabled(params)}">
9
+ <boolProp name="ResultCollector.error_logging">false</boolProp>
10
+ <objProp>
11
+ <name>saveConfig</name>
12
+ <value class="SampleSaveConfiguration">
13
+ <time>true</time>
14
+ <latency>true</latency>
15
+ <timestamp>true</timestamp>
16
+ <success>true</success>
17
+ <label>true</label>
18
+ <code>true</code>
19
+ <message>true</message>
20
+ <threadName>true</threadName>
21
+ <dataType>true</dataType>
22
+ <encoding>false</encoding>
23
+ <assertions>true</assertions>
24
+ <subresults>true</subresults>
25
+ <responseData>false</responseData>
26
+ <samplerData>false</samplerData>
27
+ <xml>true</xml>
28
+ <fieldNames>false</fieldNames>
29
+ <responseHeaders>false</responseHeaders>
30
+ <requestHeaders>false</requestHeaders>
31
+ <responseDataOnError>false</responseDataOnError>
32
+ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
33
+ <assertionsResultsToSave>0</assertionsResultsToSave>
34
+ <bytes>true</bytes>
35
+ </value>
36
+ </objProp>
37
+ <stringProp name="filename"></stringProp>
38
+ <longProp name="interval_grouping">1000</longProp>
39
+ <boolProp name="graph_aggregated">false</boolProp>
40
+ <stringProp name="include_sample_labels"></stringProp>
41
+ <stringProp name="exclude_sample_labels"></stringProp>
42
+ </kg.apc.jmeter.vizualizers.CorrectedResultCollector>
43
+ EOF
44
+ update params
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,47 @@
1
+ module RubyJmeter
2
+
3
+ class GCResponseTimesDistribution
4
+ attr_accessor :doc
5
+ include Helper
6
+ def initialize(name, params={})
7
+ @doc = Nokogiri::XML(<<-EOF.strip_heredoc)
8
+ <kg.apc.jmeter.vizualizers.CorrectedResultCollector guiclass="kg.apc.jmeter.vizualizers.ResponseTimesDistributionGui" testclass="kg.apc.jmeter.vizualizers.CorrectedResultCollector" testname="#{name}" enabled="#{enabled(params)}">
9
+ <boolProp name="ResultCollector.error_logging">false</boolProp>
10
+ <objProp>
11
+ <name>saveConfig</name>
12
+ <value class="SampleSaveConfiguration">
13
+ <time>true</time>
14
+ <latency>true</latency>
15
+ <timestamp>true</timestamp>
16
+ <success>true</success>
17
+ <label>true</label>
18
+ <code>true</code>
19
+ <message>true</message>
20
+ <threadName>true</threadName>
21
+ <dataType>true</dataType>
22
+ <encoding>false</encoding>
23
+ <assertions>true</assertions>
24
+ <subresults>true</subresults>
25
+ <responseData>false</responseData>
26
+ <samplerData>false</samplerData>
27
+ <xml>true</xml>
28
+ <fieldNames>false</fieldNames>
29
+ <responseHeaders>false</responseHeaders>
30
+ <requestHeaders>false</requestHeaders>
31
+ <responseDataOnError>false</responseDataOnError>
32
+ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
33
+ <assertionsResultsToSave>0</assertionsResultsToSave>
34
+ <bytes>true</bytes>
35
+ </value>
36
+ </objProp>
37
+ <stringProp name="filename"></stringProp>
38
+ <longProp name="interval_grouping">100</longProp>
39
+ <boolProp name="graph_aggregated">false</boolProp>
40
+ <stringProp name="include_sample_labels"></stringProp>
41
+ <stringProp name="exclude_sample_labels"></stringProp>
42
+ </kg.apc.jmeter.vizualizers.CorrectedResultCollector>
43
+ EOF
44
+ update params
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,48 @@
1
+ module RubyJmeter
2
+
3
+ class GCResponseTimesOverTime
4
+ attr_accessor :doc
5
+ include Helper
6
+ def initialize(name, params={})
7
+ @doc = Nokogiri::XML(<<-EOF.strip_heredoc)
8
+ <kg.apc.jmeter.vizualizers.CorrectedResultCollector guiclass="kg.apc.jmeter.vizualizers.ResponseTimesOverTimeGui" testclass="kg.apc.jmeter.vizualizers.CorrectedResultCollector" testname="#{name}" enabled="#{enabled(params)}">
9
+ <boolProp name="ResultCollector.error_logging">false</boolProp>
10
+ <objProp>
11
+ <name>saveConfig</name>
12
+ <value class="SampleSaveConfiguration">
13
+ <time>true</time>
14
+ <latency>true</latency>
15
+ <timestamp>true</timestamp>
16
+ <success>true</success>
17
+ <label>true</label>
18
+ <code>true</code>
19
+ <message>true</message>
20
+ <threadName>true</threadName>
21
+ <dataType>true</dataType>
22
+ <encoding>false</encoding>
23
+ <assertions>true</assertions>
24
+ <subresults>true</subresults>
25
+ <responseData>false</responseData>
26
+ <samplerData>false</samplerData>
27
+ <xml>true</xml>
28
+ <fieldNames>false</fieldNames>
29
+ <responseHeaders>false</responseHeaders>
30
+ <requestHeaders>false</requestHeaders>
31
+ <responseDataOnError>false</responseDataOnError>
32
+ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
33
+ <assertionsResultsToSave>0</assertionsResultsToSave>
34
+ <bytes>true</bytes>
35
+ </value>
36
+ </objProp>
37
+ <stringProp name="filename"></stringProp>
38
+ <longProp name="interval_grouping">500</longProp>
39
+ <boolProp name="graph_aggregated">false</boolProp>
40
+ <stringProp name="include_sample_labels"></stringProp>
41
+ <stringProp name="exclude_sample_labels"></stringProp>
42
+ </kg.apc.jmeter.vizualizers.CorrectedResultCollector>
43
+ EOF
44
+ update params
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,48 @@
1
+ module RubyJmeter
2
+
3
+ class GCResponseTimesPercentiles
4
+ attr_accessor :doc
5
+ include Helper
6
+ def initialize(name, params={})
7
+ @doc = Nokogiri::XML(<<-EOF.strip_heredoc)
8
+ <kg.apc.jmeter.vizualizers.CorrectedResultCollector guiclass="kg.apc.jmeter.vizualizers.ResponseTimesPercentilesGui" testclass="kg.apc.jmeter.vizualizers.CorrectedResultCollector" testname="#{name}" enabled="#{enabled(params)}">
9
+ <boolProp name="ResultCollector.error_logging">false</boolProp>
10
+ <objProp>
11
+ <name>saveConfig</name>
12
+ <value class="SampleSaveConfiguration">
13
+ <time>true</time>
14
+ <latency>true</latency>
15
+ <timestamp>true</timestamp>
16
+ <success>true</success>
17
+ <label>true</label>
18
+ <code>true</code>
19
+ <message>true</message>
20
+ <threadName>true</threadName>
21
+ <dataType>true</dataType>
22
+ <encoding>false</encoding>
23
+ <assertions>true</assertions>
24
+ <subresults>true</subresults>
25
+ <responseData>false</responseData>
26
+ <samplerData>false</samplerData>
27
+ <xml>true</xml>
28
+ <fieldNames>false</fieldNames>
29
+ <responseHeaders>false</responseHeaders>
30
+ <requestHeaders>false</requestHeaders>
31
+ <responseDataOnError>false</responseDataOnError>
32
+ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
33
+ <assertionsResultsToSave>0</assertionsResultsToSave>
34
+ <bytes>true</bytes>
35
+ </value>
36
+ </objProp>
37
+ <stringProp name="filename"></stringProp>
38
+ <longProp name="interval_grouping">500</longProp>
39
+ <boolProp name="graph_aggregated">false</boolProp>
40
+ <stringProp name="include_sample_labels"></stringProp>
41
+ <stringProp name="exclude_sample_labels"></stringProp>
42
+ </kg.apc.jmeter.vizualizers.CorrectedResultCollector>
43
+ EOF
44
+ update params
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,48 @@
1
+ module RubyJmeter
2
+
3
+ class GCTransactionsPerSecond
4
+ attr_accessor :doc
5
+ include Helper
6
+ def initialize(name, params={})
7
+ @doc = Nokogiri::XML(<<-EOF.strip_heredoc)
8
+ <kg.apc.jmeter.vizualizers.CorrectedResultCollector guiclass="kg.apc.jmeter.vizualizers.TransactionsPerSecondGui" testclass="kg.apc.jmeter.vizualizers.CorrectedResultCollector" testname="#{name}" enabled="#{enabled(params)}">
9
+ <boolProp name="ResultCollector.error_logging">false</boolProp>
10
+ <objProp>
11
+ <name>saveConfig</name>
12
+ <value class="SampleSaveConfiguration">
13
+ <time>true</time>
14
+ <latency>true</latency>
15
+ <timestamp>true</timestamp>
16
+ <success>true</success>
17
+ <label>true</label>
18
+ <code>true</code>
19
+ <message>true</message>
20
+ <threadName>true</threadName>
21
+ <dataType>true</dataType>
22
+ <encoding>false</encoding>
23
+ <assertions>true</assertions>
24
+ <subresults>true</subresults>
25
+ <responseData>false</responseData>
26
+ <samplerData>false</samplerData>
27
+ <xml>true</xml>
28
+ <fieldNames>false</fieldNames>
29
+ <responseHeaders>false</responseHeaders>
30
+ <requestHeaders>false</requestHeaders>
31
+ <responseDataOnError>false</responseDataOnError>
32
+ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
33
+ <assertionsResultsToSave>0</assertionsResultsToSave>
34
+ <bytes>true</bytes>
35
+ </value>
36
+ </objProp>
37
+ <stringProp name="filename"></stringProp>
38
+ <longProp name="interval_grouping">1000</longProp>
39
+ <boolProp name="graph_aggregated">false</boolProp>
40
+ <stringProp name="include_sample_labels"></stringProp>
41
+ <stringProp name="exclude_sample_labels"></stringProp>
42
+ </kg.apc.jmeter.vizualizers.CorrectedResultCollector>
43
+ EOF
44
+ update params
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,26 @@
1
+ module RubyJmeter
2
+
3
+ class GCThroughputShapingTimer
4
+ attr_accessor :doc
5
+ include Helper
6
+ def initialize(name, steps, params={})
7
+ @doc = Nokogiri::XML(<<-EOF.strip_heredoc)
8
+ <kg.apc.jmeter.timers.VariableThroughputTimer guiclass="kg.apc.jmeter.timers.VariableThroughputTimerGui" testclass="kg.apc.jmeter.timers.VariableThroughputTimer" testname="#{name}" enabled="true">
9
+ <collectionProp name="load_profile"/>
10
+ </kg.apc.jmeter.timers.VariableThroughputTimer>
11
+ EOF
12
+ steps.each_with_index do |step, index|
13
+ @doc.at_xpath('//collectionProp') <<
14
+ Nokogiri::XML(<<-EOF.strip_heredoc).children
15
+ <collectionProp name="step_#{index}">
16
+ <stringProp name="start_rps_#{index}">#{step[:start_rps]}</stringProp>
17
+ <stringProp name="end_rps_#{index}">#{step[:end_rps]}</stringProp>
18
+ <stringProp name="duration_sec_#{index}">#{step[:duration]}</stringProp>
19
+ </collectionProp>
20
+ EOF
21
+ end
22
+ update params
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,3 @@
1
+ module RubyJmeter
2
+ VERSION = "2.0"
3
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ruby-jmeter/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "ruby-jmeter"
8
+ gem.version = RubyJmeter::VERSION
9
+ gem.authors = ["Tim Koopmans"]
10
+ gem.email = ["support@flood.io"]
11
+ gem.description = %q{This is a Ruby based DSL for writing JMeter test plans}
12
+ gem.summary = %q{This is a Ruby based DSL for writing JMeter test plans}
13
+ gem.homepage = "http://github.com/flood-io/ruby-jmeter"
14
+ gem.add_dependency("rest-client")
15
+ gem.add_dependency("nokogiri")
16
+ gem.add_runtime_dependency('json-jruby') if RUBY_PLATFORM == 'java'
17
+
18
+ gem.files = `git ls-files`.split($/)
19
+ gem.executables << 'grid'
20
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ gem.require_paths = ['lib']
22
+ end
data/spec/dsl_spec.rb ADDED
@@ -0,0 +1,491 @@
1
+ require "spec_helper"
2
+ require "pry-debugger"
3
+
4
+ describe "DSL" do
5
+
6
+ describe 'aliased DSL methods' do
7
+ it "test plan should respond to aliased methods" do
8
+ test {}.should respond_to :variables
9
+ test {}.should respond_to :defaults
10
+ test {}.should respond_to :cookies
11
+ test {}.should respond_to :cache
12
+ test {}.should respond_to :header
13
+ test {}.should respond_to :auth
14
+ end
15
+ end
16
+
17
+
18
+ describe 'write to stdout and file' do
19
+ it "should output a test plan to stdout" do
20
+ $stdout.should_receive(:puts).with(/jmeterTestPlan/i)
21
+ test do
22
+ end.out
23
+ end
24
+
25
+ it "should output a test plan to jmx file" do
26
+ file = mock('file')
27
+ File.should_receive(:open).with("jmeter.jmx", "w").and_yield(file)
28
+ file.should_receive(:write).with(/jmeterTestPlan/i)
29
+ test do
30
+ end.jmx
31
+ end
32
+ end
33
+
34
+
35
+ describe 'user agent' do
36
+ let(:doc) do
37
+ test do
38
+ with_user_agent :chrome
39
+ threads
40
+ end.to_doc
41
+ end
42
+
43
+ let(:fragment) { doc.search("//HeaderManager").first }
44
+
45
+ it 'should match on user_agent' do
46
+ fragment.search(".//stringProp[@name='Header.name']").text.should == 'User-Agent'
47
+ fragment.search(".//stringProp[@name='Header.value']").text.should ==
48
+ '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'
49
+ end
50
+ end
51
+
52
+ describe 'test plan' do
53
+ it 'should allow to take params' do
54
+ test_plan = test({"TestPlan.serialize_threadgroups" => "false"}) {}
55
+ test_plan.to_doc.search("boolProp[@name='TestPlan.serialize_threadgroups']").text.should == "false"
56
+
57
+ test_plan = test({"TestPlan.serialize_threadgroups" => "true"}) {}
58
+ test_plan.to_doc.search("boolProp[@name='TestPlan.serialize_threadgroups']").text.should == "true"
59
+ end
60
+ end
61
+
62
+
63
+ describe 'thread groups' do
64
+ let(:doc) do
65
+ test do
66
+ threads count: 101, continue_forever: true, duration: 69
67
+ end.to_doc
68
+ end
69
+
70
+ let(:fragment) { doc.search("//ThreadGroup").first }
71
+
72
+ it 'should match on num_threads' do
73
+ fragment.search(".//stringProp[@name='ThreadGroup.num_threads']").text.should == '101'
74
+ end
75
+
76
+ it 'should match on continue_forever' do
77
+ fragment.search(".//boolProp[@name='LoopController.continue_forever']").text.should == 'true'
78
+ end
79
+
80
+ it 'should match on loops' do
81
+ fragment.search(".//stringProp[@name='LoopController.loops']").text.should == '-1'
82
+ end
83
+
84
+ it 'should match on duration' do
85
+ fragment.search(".//stringProp[@name='ThreadGroup.duration']").text.should == '69'
86
+ end
87
+ end
88
+
89
+
90
+ describe 'thread groups old syntax' do
91
+ let(:doc) do
92
+ test do
93
+ threads 101, continue_forever: true, duration: 69
94
+ end.to_doc
95
+ end
96
+
97
+ let(:fragment) { doc.search("//ThreadGroup").first }
98
+
99
+ it 'should match on num_threads' do
100
+ fragment.search(".//stringProp[@name='ThreadGroup.num_threads']").text.should == '101'
101
+ end
102
+
103
+ it 'should match on continue_forever' do
104
+ fragment.search(".//boolProp[@name='LoopController.continue_forever']").text.should == 'true'
105
+ end
106
+
107
+ it 'should match on loops' do
108
+ fragment.search(".//stringProp[@name='LoopController.loops']").text.should == '-1'
109
+ end
110
+
111
+ it 'should match on duration' do
112
+ fragment.search(".//stringProp[@name='ThreadGroup.duration']").text.should == '69'
113
+ end
114
+ end
115
+
116
+
117
+ describe 'transaction controller' do
118
+ let(:doc) do
119
+ test do
120
+ threads do
121
+ transaction name: "TC_01", parent: true, include_timers: true
122
+ end
123
+ end.to_doc
124
+ end
125
+
126
+ let(:fragment) { doc.search("//TransactionController").first }
127
+
128
+ it 'should match on parent' do
129
+ fragment.search(".//boolProp[@name='TransactionController.parent']").text.should == 'true'
130
+ end
131
+
132
+ it 'should match on includeTimers' do
133
+ fragment.search(".//boolProp[@name='TransactionController.includeTimers']").text.should == 'true'
134
+ end
135
+ end
136
+
137
+
138
+ describe 'throughput controller' do
139
+ let(:doc) do
140
+ test do
141
+ threads do
142
+ throughput_controller percent: 99 do
143
+ transaction name: "TC_01", parent: true, include_timers: true
144
+ end
145
+ end
146
+ end.to_doc
147
+ end
148
+
149
+ let(:fragment) { doc.search("//ThroughputController").first }
150
+
151
+ it 'should match on maxThroughput' do
152
+ # puts doc.to_xml indent: 2
153
+ fragment.search(".//intProp[@name='ThroughputController.maxThroughput']").text.should == '99'
154
+ fragment.search(".//FloatProperty/value").text.should == '99.0'
155
+ end
156
+
157
+ it 'should match on style' do
158
+ fragment.search(".//intProp[@name='ThroughputController.style']").text.should == '1'
159
+ end
160
+ end
161
+
162
+
163
+ describe 'visit' do
164
+ let(:doc) do
165
+ test do
166
+ threads do
167
+ transaction name: "TC_01", parent: true, include_timers: true do
168
+ visit url: "/home?location=melbourne", always_encode: true
169
+ end
170
+ end
171
+ end.to_doc
172
+ end
173
+
174
+ let(:fragment) { doc.search("//HTTPSamplerProxy").first }
175
+
176
+ it 'should match on path' do
177
+ fragment.search(".//stringProp[@name='HTTPSampler.path']").text.should == '/home'
178
+ end
179
+
180
+ it 'should match on always_encode' do
181
+ fragment.search(".//boolProp[@name='HTTPArgument.always_encode']").text.should == 'true'
182
+ end
183
+ end
184
+
185
+
186
+ describe 'visit old syntax' do
187
+ let(:doc) do
188
+ test do
189
+ threads do
190
+ visit "/home?location=melbourne", always_encode: true
191
+ end
192
+ end.to_doc
193
+ end
194
+
195
+ let(:fragment) { doc.search("//HTTPSamplerProxy").first }
196
+
197
+ it 'should match on path' do
198
+ fragment.search(".//stringProp[@name='HTTPSampler.path']").text.should == '/home'
199
+ end
200
+ end
201
+
202
+
203
+ describe 'https' do
204
+ let(:doc) do
205
+ test do
206
+ threads do
207
+ transaction name: "TC_01", parent: true, include_timers: true do
208
+ visit url: "https://example.com"
209
+ end
210
+ end
211
+ end.to_doc
212
+ end
213
+
214
+ let(:fragment) { doc.search("//HTTPSamplerProxy").first }
215
+
216
+ it 'should match on protocol' do
217
+ fragment.search(".//stringProp[@name='HTTPSampler.protocol']").text.should == 'https'
218
+ end
219
+ end
220
+
221
+
222
+ describe 'xhr' do
223
+ let(:doc) do
224
+ test do
225
+ threads do
226
+ transaction name: "TC_02", parent: true, include_timers: true do
227
+ visit url: "/" do
228
+ with_xhr
229
+ end
230
+ end
231
+ end
232
+ end.to_doc
233
+ end
234
+
235
+ let(:fragment) { doc.search("//HeaderManager").first }
236
+
237
+ it 'should match on XHR' do
238
+ fragment.search(".//stringProp[@name='Header.value']").text.should == 'XMLHttpRequest'
239
+ end
240
+ end
241
+
242
+
243
+ describe 'submit' do
244
+ let(:doc) do
245
+ test do
246
+ threads do
247
+ transaction name: "TC_03", parent: true, include_timers: true do
248
+ submit url: "/", fill_in: { username: 'tim', password: 'password' }
249
+ end
250
+ end
251
+ end.to_doc
252
+ end
253
+
254
+ let(:fragment) { doc.search("//HTTPSamplerProxy").first }
255
+
256
+ it 'should match on POST' do
257
+ fragment.search(".//stringProp[@name='HTTPSampler.method']").text.should == 'POST'
258
+ end
259
+ end
260
+
261
+
262
+ describe 'If' do
263
+ let(:doc) do
264
+ test do
265
+ threads do
266
+ If condition: '2>1' do
267
+ visit url: "/"
268
+ end
269
+ end
270
+ end.to_doc
271
+ end
272
+
273
+ let(:fragment) { doc.search("//IfController").first }
274
+
275
+ it 'should match on If' do
276
+ fragment.search(".//stringProp[@name='IfController.condition']").text.should == '2>1'
277
+ end
278
+ end
279
+
280
+
281
+ describe 'exists' do
282
+ let(:doc) do
283
+ test do
284
+ threads do
285
+ exists 'apple' do
286
+ visit url: "/"
287
+ end
288
+ end
289
+ end.to_doc
290
+ end
291
+
292
+ let(:fragment) { doc.search("//IfController").first }
293
+
294
+ it 'should match on exists' do
295
+ fragment.search(".//stringProp[@name='IfController.condition']").text.should == "'${apple}'.length > 0"
296
+ end
297
+ end
298
+
299
+
300
+ describe 'While' do
301
+ let(:doc) do
302
+ test do
303
+ threads do
304
+ While condition: 'true' do
305
+ visit url: "/"
306
+ end
307
+ end
308
+ end.to_doc
309
+ end
310
+
311
+ let(:fragment) { doc.search("//WhileController").first }
312
+
313
+ it 'should match on While' do
314
+ fragment.search(".//stringProp[@name='WhileController.condition']").text.should == 'true'
315
+ end
316
+ end
317
+
318
+
319
+ describe 'Loop' do
320
+ let(:doc) do
321
+ test do
322
+ threads do
323
+ Loop count: 5 do
324
+ visit url: "/"
325
+ end
326
+ end
327
+ end.to_doc
328
+ end
329
+
330
+ let(:fragment) { doc.search("//LoopController").first }
331
+
332
+ it 'should match on Loops' do
333
+ fragment.search(".//stringProp[@name='LoopController.loops']").text.should == '5'
334
+ end
335
+ end
336
+
337
+
338
+ describe 'Counter' do
339
+ let(:doc) do
340
+ test do
341
+ threads do
342
+ visit url: "/" do
343
+ counter start: 1, per_user: true
344
+ end
345
+ end
346
+ end.to_doc
347
+ end
348
+
349
+ let(:fragment) { doc.search("//CounterConfig").first }
350
+
351
+ it 'should match on 5 Loops' do
352
+ fragment.search(".//boolProp[@name='CounterConfig.per_user']").text.should == 'true'
353
+ end
354
+ end
355
+
356
+
357
+ describe 'Switch' do
358
+ let(:doc) do
359
+ test do
360
+ threads do
361
+ Switch value: 'cat' do
362
+ visit url: "/"
363
+ end
364
+ end
365
+ end.to_doc
366
+ end
367
+
368
+ let(:fragment) { doc.search("//SwitchController").first }
369
+
370
+ it 'should match on Switch' do
371
+ fragment.search(".//stringProp[@name='SwitchController.value']").text.should == 'cat'
372
+ end
373
+ end
374
+
375
+ describe 'regex extract' do
376
+ let(:doc) do
377
+ test do
378
+ extract regex: 'pattern', name: 'my_regex'
379
+ end.to_doc
380
+ end
381
+
382
+ let(:fragment) { doc.search("//RegexExtractor").first }
383
+
384
+ it 'should match on refname' do
385
+ fragment.search(".//stringProp[@name='RegexExtractor.refname']").text.should == 'my_regex'
386
+ end
387
+ end
388
+
389
+
390
+ describe 'xpath extract' do
391
+ let(:doc) do
392
+ test do
393
+ extract xpath: '//node', name: 'my_xpath'
394
+ end.to_doc
395
+ end
396
+
397
+ let(:fragment) { doc.search("//XPathExtractor").first }
398
+
399
+ it 'should match on refname' do
400
+ fragment.search(".//stringProp[@name='XPathExtractor.refname']").text.should == 'my_xpath'
401
+ end
402
+ end
403
+
404
+
405
+ describe 'assertions' do
406
+
407
+ describe 'scope all' do
408
+ let(:doc) do
409
+ test do
410
+ visit '/' do
411
+ assert contains: 'Welcome'
412
+ end
413
+ end.to_doc
414
+ end
415
+
416
+ let(:fragment) { doc.search("//ResponseAssertion").first }
417
+
418
+ it 'should match on match' do
419
+ fragment.search(".//stringProp[@name='match']").text.should == 'Welcome'
420
+ end
421
+
422
+ it 'should match on scope' do
423
+ fragment.search(".//stringProp[@name='Assertion.scope']").text.should == 'all'
424
+ end
425
+
426
+ it 'should match on test_type' do
427
+ fragment.search(".//intProp[@name='Assertion.test_type']").text.should == '2'
428
+ end
429
+ end
430
+
431
+ describe 'scope main' do
432
+ let(:doc) do
433
+ test do
434
+ visit '/' do
435
+ assert contains: 'Welcome', scope: 'main'
436
+ end
437
+ end.to_doc
438
+ end
439
+
440
+ let(:fragment) { doc.search("//ResponseAssertion").first }
441
+
442
+ it 'should match on scope' do
443
+ fragment.search(".//stringProp[@name='Assertion.scope']").text.should == ""
444
+ end
445
+ end
446
+ end
447
+
448
+
449
+ describe 'Nested controllers' do
450
+ let(:doc) do
451
+ test do
452
+ Simple name: 'node1.1' do
453
+ Simple name: 'node2.1'
454
+ Simple name: 'node2.2' do
455
+ Simple name: 'node3.1'
456
+ end
457
+ Simple name: 'node2.3'
458
+ end
459
+ Simple name: 'node1.2'
460
+ end.to_doc
461
+ end
462
+
463
+ let(:node1_1) { doc.search("//GenericController[@testname='node1.1']").first }
464
+ let(:node1_2) { doc.search("//GenericController[@testname='node1.2']").first }
465
+
466
+ let(:node2_1) { doc.search("//GenericController[@testname='node2.1']").first }
467
+ let(:node2_2) { doc.search("//GenericController[@testname='node2.2']").first }
468
+ let(:node2_3) { doc.search("//GenericController[@testname='node2.3']").first }
469
+
470
+ let(:node3_1) { doc.search("//GenericController[@testname='node3.1']").first }
471
+
472
+ it 'nodes should have hashTree as its parent' do
473
+ [node1_1, node1_2, node2_1, node2_2, node2_3, node3_1].each do |node|
474
+ node.parent.name.should == 'hashTree'
475
+ end
476
+ end
477
+
478
+ describe 'node3_1' do
479
+ it 'parent parent should be node2_2' do
480
+ node3_1.parent.should == node2_2.next
481
+ end
482
+ end
483
+
484
+ describe 'node1_2' do
485
+ it 'previous non hashTree sibling is node1_1' do
486
+ node1_2.previous.previous.should == node1_1
487
+ end
488
+ end
489
+
490
+ end
491
+ end