ruby-jmeter 2.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 (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