jmeter_perf 1.0.9

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 (275) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +19 -0
  4. data/.standard.yml +4 -0
  5. data/CHANGELOG.md +18 -0
  6. data/DSL.md +235 -0
  7. data/README.md +24 -0
  8. data/Rakefile +12 -0
  9. data/example/Gemfile +39 -0
  10. data/example/Gemfile.lock +232 -0
  11. data/example/README.md +3 -0
  12. data/example/Rakefile +6 -0
  13. data/example/app/controllers/application_controller.rb +2 -0
  14. data/example/app/controllers/test_controller.rb +15 -0
  15. data/example/bin/bundle +109 -0
  16. data/example/bin/docker-entrypoint +8 -0
  17. data/example/bin/rails +4 -0
  18. data/example/bin/rake +4 -0
  19. data/example/bin/setup +33 -0
  20. data/example/config/application.rb +44 -0
  21. data/example/config/boot.rb +3 -0
  22. data/example/config/credentials.yml.enc +1 -0
  23. data/example/config/database.yml +25 -0
  24. data/example/config/environment.rb +5 -0
  25. data/example/config/environments/development.rb +64 -0
  26. data/example/config/environments/production.rb +82 -0
  27. data/example/config/environments/test.rb +61 -0
  28. data/example/config/initializers/cors.rb +16 -0
  29. data/example/config/initializers/filter_parameter_logging.rb +8 -0
  30. data/example/config/initializers/inflections.rb +16 -0
  31. data/example/config/locales/en.yml +31 -0
  32. data/example/config/puma.rb +35 -0
  33. data/example/config/routes.rb +5 -0
  34. data/example/config.ru +7 -0
  35. data/example/fast.log +49 -0
  36. data/example/jmeter.log +28 -0
  37. data/example/lib/tasks/test.rake +40 -0
  38. data/example/log/.keep +0 -0
  39. data/example/public/robots.txt +1 -0
  40. data/example/random.log +49 -0
  41. data/example/slow.log +49 -0
  42. data/example/vendor/.keep +0 -0
  43. data/lib/Rakefile +4 -0
  44. data/lib/jmeter_perf/dsl/access_log_sampler.rb +38 -0
  45. data/lib/jmeter_perf/dsl/aggregate_graph.rb +61 -0
  46. data/lib/jmeter_perf/dsl/aggregate_report.rb +61 -0
  47. data/lib/jmeter_perf/dsl/ajp13_sampler.rb +47 -0
  48. data/lib/jmeter_perf/dsl/assertion_results.rb +61 -0
  49. data/lib/jmeter_perf/dsl/bean_shell_assertion.rb +34 -0
  50. data/lib/jmeter_perf/dsl/bean_shell_listener.rb +34 -0
  51. data/lib/jmeter_perf/dsl/bean_shell_postprocessor.rb +34 -0
  52. data/lib/jmeter_perf/dsl/bean_shell_preprocessor.rb +34 -0
  53. data/lib/jmeter_perf/dsl/bean_shell_sampler.rb +34 -0
  54. data/lib/jmeter_perf/dsl/bean_shell_timer.rb +34 -0
  55. data/lib/jmeter_perf/dsl/bsf_assertion.rb +34 -0
  56. data/lib/jmeter_perf/dsl/bsf_listener.rb +34 -0
  57. data/lib/jmeter_perf/dsl/bsf_postprocessor.rb +34 -0
  58. data/lib/jmeter_perf/dsl/bsf_preprocessor.rb +34 -0
  59. data/lib/jmeter_perf/dsl/bsf_sampler.rb +34 -0
  60. data/lib/jmeter_perf/dsl/bsf_timer.rb +34 -0
  61. data/lib/jmeter_perf/dsl/compare_assertion.rb +33 -0
  62. data/lib/jmeter_perf/dsl/comparison_assertion_visualizer.rb +61 -0
  63. data/lib/jmeter_perf/dsl/constant_throughput_timer.rb +32 -0
  64. data/lib/jmeter_perf/dsl/constant_timer.rb +31 -0
  65. data/lib/jmeter_perf/dsl/counter.rb +37 -0
  66. data/lib/jmeter_perf/dsl/css_jquery_extractor.rb +37 -0
  67. data/lib/jmeter_perf/dsl/csv_data_set_config.rb +39 -0
  68. data/lib/jmeter_perf/dsl/debug_postprocessor.rb +34 -0
  69. data/lib/jmeter_perf/dsl/debug_sampler.rb +33 -0
  70. data/lib/jmeter_perf/dsl/distribution_graphalpha.rb +61 -0
  71. data/lib/jmeter_perf/dsl/duration_assertion.rb +31 -0
  72. data/lib/jmeter_perf/dsl/for_each_controller.rb +33 -0
  73. data/lib/jmeter_perf/dsl/ftp_request.rb +40 -0
  74. data/lib/jmeter_perf/dsl/ftp_request_defaults.rb +38 -0
  75. data/lib/jmeter_perf/dsl/gaussian_random_timer.rb +32 -0
  76. data/lib/jmeter_perf/dsl/generate_summary_results.rb +29 -0
  77. data/lib/jmeter_perf/dsl/graph_results.rb +61 -0
  78. data/lib/jmeter_perf/dsl/html_assertion.rb +36 -0
  79. data/lib/jmeter_perf/dsl/html_link_parser.rb +29 -0
  80. data/lib/jmeter_perf/dsl/html_parameter_mask.rb +38 -0
  81. data/lib/jmeter_perf/dsl/http_authorization_manager.rb +39 -0
  82. data/lib/jmeter_perf/dsl/http_cache_manager.rb +32 -0
  83. data/lib/jmeter_perf/dsl/http_cookie_manager.rb +34 -0
  84. data/lib/jmeter_perf/dsl/http_header_manager.rb +36 -0
  85. data/lib/jmeter_perf/dsl/http_request.rb +47 -0
  86. data/lib/jmeter_perf/dsl/http_request_defaults.rb +53 -0
  87. data/lib/jmeter_perf/dsl/http_url_rewriting_modifier.rb +36 -0
  88. data/lib/jmeter_perf/dsl/if_controller.rb +33 -0
  89. data/lib/jmeter_perf/dsl/include_controller.rb +31 -0
  90. data/lib/jmeter_perf/dsl/j_unit_request.rb +43 -0
  91. data/lib/jmeter_perf/dsl/java_request.rb +75 -0
  92. data/lib/jmeter_perf/dsl/java_request_defaults.rb +75 -0
  93. data/lib/jmeter_perf/dsl/jdbc_connection_configuration.rb +43 -0
  94. data/lib/jmeter_perf/dsl/jdbc_postprocessor.rb +39 -0
  95. data/lib/jmeter_perf/dsl/jdbc_preprocessor.rb +39 -0
  96. data/lib/jmeter_perf/dsl/jdbc_request.rb +39 -0
  97. data/lib/jmeter_perf/dsl/jms_pointto_point.rb +47 -0
  98. data/lib/jmeter_perf/dsl/jms_publisher.rb +49 -0
  99. data/lib/jmeter_perf/dsl/jms_subscriber.rb +41 -0
  100. data/lib/jmeter_perf/dsl/json_path_postprocessor.rb +33 -0
  101. data/lib/jmeter_perf/dsl/jsr223_assertion.rb +35 -0
  102. data/lib/jmeter_perf/dsl/jsr223_listener.rb +35 -0
  103. data/lib/jmeter_perf/dsl/jsr223_postprocessor.rb +35 -0
  104. data/lib/jmeter_perf/dsl/jsr223_preprocessor.rb +35 -0
  105. data/lib/jmeter_perf/dsl/jsr223_sampler.rb +35 -0
  106. data/lib/jmeter_perf/dsl/jsr223_timer.rb +35 -0
  107. data/lib/jmeter_perf/dsl/keystore_configuration.rb +34 -0
  108. data/lib/jmeter_perf/dsl/ldap_extended_request.rb +48 -0
  109. data/lib/jmeter_perf/dsl/ldap_extended_request_defaults.rb +48 -0
  110. data/lib/jmeter_perf/dsl/ldap_request.rb +41 -0
  111. data/lib/jmeter_perf/dsl/ldap_request_defaults.rb +45 -0
  112. data/lib/jmeter_perf/dsl/login_config_element.rb +32 -0
  113. data/lib/jmeter_perf/dsl/loop_controller.rb +32 -0
  114. data/lib/jmeter_perf/dsl/mail_reader_sampler.rb +43 -0
  115. data/lib/jmeter_perf/dsl/mailer_visualizer.rb +70 -0
  116. data/lib/jmeter_perf/dsl/md5_hex_assertion.rb +31 -0
  117. data/lib/jmeter_perf/dsl/module_controller.rb +31 -0
  118. data/lib/jmeter_perf/dsl/monitor_results.rb +61 -0
  119. data/lib/jmeter_perf/dsl/once_only_controller.rb +29 -0
  120. data/lib/jmeter_perf/dsl/os_process_sampler.rb +40 -0
  121. data/lib/jmeter_perf/dsl/poisson_random_timer.rb +32 -0
  122. data/lib/jmeter_perf/dsl/random_controller.rb +31 -0
  123. data/lib/jmeter_perf/dsl/random_order_controller.rb +29 -0
  124. data/lib/jmeter_perf/dsl/random_variable.rb +36 -0
  125. data/lib/jmeter_perf/dsl/recording_controller.rb +29 -0
  126. data/lib/jmeter_perf/dsl/reg_ex_user_parameters.rb +33 -0
  127. data/lib/jmeter_perf/dsl/regular_expression_extractor.rb +38 -0
  128. data/lib/jmeter_perf/dsl/response_assertion.rb +37 -0
  129. data/lib/jmeter_perf/dsl/response_time_graph.rb +61 -0
  130. data/lib/jmeter_perf/dsl/result_status_action_handler.rb +31 -0
  131. data/lib/jmeter_perf/dsl/runtime_controller.rb +31 -0
  132. data/lib/jmeter_perf/dsl/save_responses_to_a_file.rb +35 -0
  133. data/lib/jmeter_perf/dsl/simple_config_element.rb +29 -0
  134. data/lib/jmeter_perf/dsl/simple_controller.rb +29 -0
  135. data/lib/jmeter_perf/dsl/simple_data_writer.rb +61 -0
  136. data/lib/jmeter_perf/dsl/smime_assertion.rb +41 -0
  137. data/lib/jmeter_perf/dsl/smtp_sampler.rb +57 -0
  138. data/lib/jmeter_perf/dsl/soap_xml_rpc_request.rb +39 -0
  139. data/lib/jmeter_perf/dsl/spline_visualizer.rb +61 -0
  140. data/lib/jmeter_perf/dsl/summary_report.rb +61 -0
  141. data/lib/jmeter_perf/dsl/switch_controller.rb +31 -0
  142. data/lib/jmeter_perf/dsl/synchronizing_timer.rb +32 -0
  143. data/lib/jmeter_perf/dsl/tcp_sampler.rb +39 -0
  144. data/lib/jmeter_perf/dsl/tcp_sampler_config.rb +37 -0
  145. data/lib/jmeter_perf/dsl/test_action.rb +33 -0
  146. data/lib/jmeter_perf/dsl/test_fragment.rb +29 -0
  147. data/lib/jmeter_perf/dsl/test_plan.rb +37 -0
  148. data/lib/jmeter_perf/dsl/thread_group.rb +43 -0
  149. data/lib/jmeter_perf/dsl/throughput_controller.rb +38 -0
  150. data/lib/jmeter_perf/dsl/transaction_controller.rb +32 -0
  151. data/lib/jmeter_perf/dsl/uniform_random_timer.rb +32 -0
  152. data/lib/jmeter_perf/dsl/user_defined_variables.rb +39 -0
  153. data/lib/jmeter_perf/dsl/user_parameters.rb +36 -0
  154. data/lib/jmeter_perf/dsl/view_results_in_table.rb +61 -0
  155. data/lib/jmeter_perf/dsl/view_results_tree.rb +61 -0
  156. data/lib/jmeter_perf/dsl/while_controller.rb +31 -0
  157. data/lib/jmeter_perf/dsl/x_path_assertion.rb +37 -0
  158. data/lib/jmeter_perf/dsl/x_path_extractor.rb +37 -0
  159. data/lib/jmeter_perf/dsl/xml_assertion.rb +29 -0
  160. data/lib/jmeter_perf/dsl/xml_schema_assertion.rb +31 -0
  161. data/lib/jmeter_perf/extend/assertions/response_assertion.rb +38 -0
  162. data/lib/jmeter_perf/extend/config_elements/header_manager.rb +13 -0
  163. data/lib/jmeter_perf/extend/config_elements/http_cache_manager.rb +12 -0
  164. data/lib/jmeter_perf/extend/config_elements/http_cookie_manager.rb +39 -0
  165. data/lib/jmeter_perf/extend/config_elements/http_request_defaults.rb +55 -0
  166. data/lib/jmeter_perf/extend/config_elements/user_defined_variables.rb +13 -0
  167. data/lib/jmeter_perf/extend/config_elements/user_parameters.rb +31 -0
  168. data/lib/jmeter_perf/extend/controllers/foreach_controller.rb +31 -0
  169. data/lib/jmeter_perf/extend/controllers/loop_controller.rb +11 -0
  170. data/lib/jmeter_perf/extend/controllers/module_controller.rb +26 -0
  171. data/lib/jmeter_perf/extend/controllers/throughput_controller.rb +15 -0
  172. data/lib/jmeter_perf/extend/controllers/transaction_controller.rb +14 -0
  173. data/lib/jmeter_perf/extend/misc/exists.rb +13 -0
  174. data/lib/jmeter_perf/extend/misc/rsync.rb +24 -0
  175. data/lib/jmeter_perf/extend/misc/uuid.rb +12 -0
  176. data/lib/jmeter_perf/extend/misc/with_helpers.rb +27 -0
  177. data/lib/jmeter_perf/extend/plugins/jmeter_plugins.rb +124 -0
  178. data/lib/jmeter_perf/extend/processors/extract.rb +27 -0
  179. data/lib/jmeter_perf/extend/processors/regular_expression_extractor.rb +27 -0
  180. data/lib/jmeter_perf/extend/samplers/http_request.rb +66 -0
  181. data/lib/jmeter_perf/extend/samplers/jms_pointtopoint.rb +23 -0
  182. data/lib/jmeter_perf/extend/samplers/soapxmlrpc_request.rb +10 -0
  183. data/lib/jmeter_perf/extend/threads/thread_group.rb +19 -0
  184. data/lib/jmeter_perf/extend/timers/constant_throughput_timer.rb +11 -0
  185. data/lib/jmeter_perf/extend/timers/random_timer.rb +14 -0
  186. data/lib/jmeter_perf/helpers/dsl_generator.rb +157 -0
  187. data/lib/jmeter_perf/helpers/fallback_content_proxy.rb +96 -0
  188. data/lib/jmeter_perf/helpers/helper.rb +63 -0
  189. data/lib/jmeter_perf/helpers/parser.rb +143 -0
  190. data/lib/jmeter_perf/helpers/running_statistics.rb +62 -0
  191. data/lib/jmeter_perf/helpers/string.rb +60 -0
  192. data/lib/jmeter_perf/helpers/user-agents.rb +42 -0
  193. data/lib/jmeter_perf/plugins/active_threads_over_time.rb +59 -0
  194. data/lib/jmeter_perf/plugins/composite_graph.rb +77 -0
  195. data/lib/jmeter_perf/plugins/console_status_logger.rb +19 -0
  196. data/lib/jmeter_perf/plugins/dummy_sampler.rb +30 -0
  197. data/lib/jmeter_perf/plugins/jmx_collector.rb +74 -0
  198. data/lib/jmeter_perf/plugins/json_path_assertion.rb +23 -0
  199. data/lib/jmeter_perf/plugins/json_path_extractor.rb +22 -0
  200. data/lib/jmeter_perf/plugins/latencies_over_time.rb +53 -0
  201. data/lib/jmeter_perf/plugins/loadosophia_uploader.rb +66 -0
  202. data/lib/jmeter_perf/plugins/perfmon_collector.rb +87 -0
  203. data/lib/jmeter_perf/plugins/redis_data_set.rb +43 -0
  204. data/lib/jmeter_perf/plugins/response_codes_per_second.rb +53 -0
  205. data/lib/jmeter_perf/plugins/response_times_distribution.rb +53 -0
  206. data/lib/jmeter_perf/plugins/response_times_over_time.rb +53 -0
  207. data/lib/jmeter_perf/plugins/response_times_percentiles.rb +54 -0
  208. data/lib/jmeter_perf/plugins/stepping_thread_group.rb +34 -0
  209. data/lib/jmeter_perf/plugins/transactions_per_second.rb +53 -0
  210. data/lib/jmeter_perf/plugins/ultimate_thread_group.rb +28 -0
  211. data/lib/jmeter_perf/plugins/variable_throughput_timer.rb +35 -0
  212. data/lib/jmeter_perf/report/comparator.rb +258 -0
  213. data/lib/jmeter_perf/report/summary.rb +268 -0
  214. data/lib/jmeter_perf/tasks/dsl.rake +19 -0
  215. data/lib/jmeter_perf/version.rb +5 -0
  216. data/lib/jmeter_perf/views/report_template.html.erb +114 -0
  217. data/lib/jmeter_perf.rb +183 -0
  218. data/lib/specifications/idl.xml +1494 -0
  219. data/sig/jmeter_perf.rbs +195 -0
  220. data/sorbet/config +5 -0
  221. data/sorbet/rbi/annotations/.gitattributes +1 -0
  222. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  223. data/sorbet/rbi/gems/.gitattributes +1 -0
  224. data/sorbet/rbi/gems/ast@2.4.2.rbi +585 -0
  225. data/sorbet/rbi/gems/bump@0.10.0.rbi +169 -0
  226. data/sorbet/rbi/gems/byebug@11.1.3.rbi +3607 -0
  227. data/sorbet/rbi/gems/coderay@1.1.3.rbi +3427 -0
  228. data/sorbet/rbi/gems/diff-lcs@1.5.1.rbi +1131 -0
  229. data/sorbet/rbi/gems/docile@1.4.1.rbi +377 -0
  230. data/sorbet/rbi/gems/erubi@1.13.0.rbi +150 -0
  231. data/sorbet/rbi/gems/json@2.7.2.rbi +1562 -0
  232. data/sorbet/rbi/gems/language_server-protocol@3.17.0.3.rbi +14238 -0
  233. data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +240 -0
  234. data/sorbet/rbi/gems/method_source@1.1.0.rbi +304 -0
  235. data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
  236. data/sorbet/rbi/gems/nokogiri@1.16.7.rbi +7311 -0
  237. data/sorbet/rbi/gems/parallel@1.26.3.rbi +291 -0
  238. data/sorbet/rbi/gems/parser@3.3.5.0.rbi +5519 -0
  239. data/sorbet/rbi/gems/prism@1.2.0.rbi +39085 -0
  240. data/sorbet/rbi/gems/pry-byebug@3.10.1.rbi +1151 -0
  241. data/sorbet/rbi/gems/pry@0.14.2.rbi +10076 -0
  242. data/sorbet/rbi/gems/racc@1.8.1.rbi +162 -0
  243. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +403 -0
  244. data/sorbet/rbi/gems/rake@13.2.1.rbi +3074 -0
  245. data/sorbet/rbi/gems/rbi@0.2.1.rbi +4535 -0
  246. data/sorbet/rbi/gems/rbtree3@0.7.1.rbi +9 -0
  247. data/sorbet/rbi/gems/regexp_parser@2.9.2.rbi +3772 -0
  248. data/sorbet/rbi/gems/rexml@3.3.8.rbi +4858 -0
  249. data/sorbet/rbi/gems/rspec-core@3.13.1.rbi +11132 -0
  250. data/sorbet/rbi/gems/rspec-expectations@3.13.3.rbi +8183 -0
  251. data/sorbet/rbi/gems/rspec-mocks@3.13.1.rbi +5341 -0
  252. data/sorbet/rbi/gems/rspec-support@3.13.1.rbi +1630 -0
  253. data/sorbet/rbi/gems/rspec@3.13.0.rbi +83 -0
  254. data/sorbet/rbi/gems/rubocop-ast@1.32.3.rbi +7054 -0
  255. data/sorbet/rbi/gems/rubocop-performance@1.21.1.rbi +9 -0
  256. data/sorbet/rbi/gems/rubocop@1.65.1.rbi +58182 -0
  257. data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1318 -0
  258. data/sorbet/rbi/gems/simplecov-html@0.13.1.rbi +225 -0
  259. data/sorbet/rbi/gems/simplecov@0.22.0.rbi +2149 -0
  260. data/sorbet/rbi/gems/simplecov_json_formatter@0.1.4.rbi +9 -0
  261. data/sorbet/rbi/gems/spoom@1.5.0.rbi +4932 -0
  262. data/sorbet/rbi/gems/standard-custom@1.0.2.rbi +9 -0
  263. data/sorbet/rbi/gems/standard-performance@1.4.0.rbi +9 -0
  264. data/sorbet/rbi/gems/standard@1.40.0.rbi +926 -0
  265. data/sorbet/rbi/gems/tapioca@0.16.3.rbi +3596 -0
  266. data/sorbet/rbi/gems/tdigest@0.2.1.rbi +170 -0
  267. data/sorbet/rbi/gems/thor@1.3.2.rbi +4378 -0
  268. data/sorbet/rbi/gems/unicode-display_width@2.6.0.rbi +66 -0
  269. data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
  270. data/sorbet/rbi/gems/yard@0.9.37.rbi +18379 -0
  271. data/sorbet/rbi/todo.rbi +31 -0
  272. data/sorbet/tapioca/config.yml +13 -0
  273. data/sorbet/tapioca/require.rb +15 -0
  274. data/tasks/dsl.rake +22 -0
  275. metadata +355 -0
@@ -0,0 +1,53 @@
1
+ module JmeterPerf
2
+ module Plugins
3
+ class ResponseTimesOverTime
4
+ attr_accessor :doc
5
+ include JmeterPerf::Helpers::XmlDocumentUpdater
6
+ def initialize(params = {})
7
+ testname = params.is_a?(Array) ? "ResponseTimesOverTime" : (params[:name] || "ResponseTimesOverTime")
8
+ @doc = Nokogiri::XML(
9
+ JmeterPerf::Helpers::String.strip_heredoc(
10
+ <<-EOF
11
+ <kg.apc.jmeter.vizualizers.CorrectedResultCollector guiclass="kg.apc.jmeter.vizualizers.ResponseTimesOverTimeGui" testclass="kg.apc.jmeter.vizualizers.CorrectedResultCollector" testname="#{testname}" enabled="#{enabled(params)}">
12
+ <boolProp name="ResultCollector.error_logging">false</boolProp>
13
+ <objProp>
14
+ <name>saveConfig</name>
15
+ <value class="SampleSaveConfiguration">
16
+ <time>true</time>
17
+ <latency>true</latency>
18
+ <timestamp>true</timestamp>
19
+ <success>true</success>
20
+ <label>true</label>
21
+ <code>true</code>
22
+ <message>true</message>
23
+ <threadName>true</threadName>
24
+ <dataType>true</dataType>
25
+ <encoding>false</encoding>
26
+ <assertions>true</assertions>
27
+ <subresults>true</subresults>
28
+ <responseData>false</responseData>
29
+ <samplerData>false</samplerData>
30
+ <xml>true</xml>
31
+ <fieldNames>false</fieldNames>
32
+ <responseHeaders>false</responseHeaders>
33
+ <requestHeaders>false</requestHeaders>
34
+ <responseDataOnError>false</responseDataOnError>
35
+ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
36
+ <assertionsResultsToSave>0</assertionsResultsToSave>
37
+ <bytes>true</bytes>
38
+ </value>
39
+ </objProp>
40
+ <stringProp name="filename"></stringProp>
41
+ <longProp name="interval_grouping">500</longProp>
42
+ <boolProp name="graph_aggregated">false</boolProp>
43
+ <stringProp name="include_sample_labels"></stringProp>
44
+ <stringProp name="exclude_sample_labels"></stringProp>
45
+ </kg.apc.jmeter.vizualizers.CorrectedResultCollector>
46
+ EOF
47
+ )
48
+ )
49
+ update params
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,54 @@
1
+ module JmeterPerf
2
+ module Plugins
3
+ class ResponseTimesPercentiles
4
+ attr_accessor :doc
5
+ include JmeterPerf::Helpers::XmlDocumentUpdater
6
+ def initialize(params = {})
7
+ testname = params.is_a?(Array) ? "ResponseTimesPercentiles" : (params[:name] || "ResponseTimesPercentiles")
8
+ @doc = Nokogiri::XML(
9
+ JmeterPerf::Helpers::String.strip_heredoc(
10
+ <<-EOF
11
+ <kg.apc.jmeter.vizualizers.CorrectedResultCollector guiclass="kg.apc.jmeter.vizualizers.ResponseTimesPercentilesGui" testclass="kg.apc.jmeter.vizualizers.CorrectedResultCollector" testname="#{testname}" enabled="#{enabled(params)}">
12
+ <boolProp name="ResultCollector.error_logging">false</boolProp>
13
+ <objProp>
14
+ <name>saveConfig</name>
15
+ <value class="SampleSaveConfiguration">
16
+ <time>true</time>
17
+ <latency>true</latency>
18
+ <timestamp>true</timestamp>
19
+ <success>true</success>
20
+ <label>true</label>
21
+ <code>true</code>
22
+ <message>true</message>
23
+ <threadName>true</threadName>
24
+ <dataType>true</dataType>
25
+ <encoding>false</encoding>
26
+ <assertions>true</assertions>
27
+ <subresults>true</subresults>
28
+ <responseData>false</responseData>
29
+ <samplerData>false</samplerData>
30
+ <xml>true</xml>
31
+ <fieldNames>false</fieldNames>
32
+ <responseHeaders>false</responseHeaders>
33
+ <requestHeaders>false</requestHeaders>
34
+ <responseDataOnError>false</responseDataOnError>
35
+ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
36
+ <assertionsResultsToSave>0</assertionsResultsToSave>
37
+ <bytes>true</bytes>
38
+ </value>
39
+ </objProp>
40
+ <stringProp name="filename"></stringProp>
41
+ <longProp name="interval_grouping">500</longProp>
42
+ <boolProp name="graph_aggregated">false</boolProp>
43
+ <stringProp name="include_sample_labels"></stringProp>
44
+ <stringProp name="exclude_sample_labels"></stringProp>
45
+ </kg.apc.jmeter.vizualizers.CorrectedResultCollector>
46
+ EOF
47
+ )
48
+ )
49
+ update params
50
+ update_at_xpath params if params.is_a?(Hash) && params[:update_at_xpath]
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,34 @@
1
+ module JmeterPerf
2
+ module Plugins
3
+ class SteppingThreadGroup
4
+ attr_accessor :doc
5
+ include JmeterPerf::Helpers::XmlDocumentUpdater
6
+ def initialize(params = {})
7
+ testname = params.is_a?(Array) ? "SteppingThreadGroup" : (params[:name] || "SteppingThreadGroup")
8
+ @doc = Nokogiri::XML(
9
+ JmeterPerf::Helpers::String.strip_heredoc(
10
+ <<-EOF
11
+ <kg.apc.jmeter.threads.SteppingThreadGroup guiclass="kg.apc.jmeter.threads.SteppingThreadGroupGui" testclass="kg.apc.jmeter.threads.SteppingThreadGroup" testname="#{testname}" enabled="true">
12
+ <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
13
+ <stringProp name="ThreadGroup.num_threads">#{params[:total_threads]}</stringProp>
14
+ <stringProp name="Threads initial delay">#{params[:initial_delay]}</stringProp>
15
+ <stringProp name="Start users count">#{params[:start_threads]}</stringProp>
16
+ <stringProp name="Start users count burst">#{params[:add_threads]}</stringProp>
17
+ <stringProp name="Start users period">#{params[:start_every]}</stringProp>
18
+ <stringProp name="Stop users count">#{params[:stop_threads]}</stringProp>
19
+ <stringProp name="Stop users period">#{params[:stop_every]}</stringProp>
20
+ <stringProp name="flighttime">#{params[:flight_time]}</stringProp>
21
+ <stringProp name="rampUp">#{params[:rampup]}</stringProp>
22
+ <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
23
+ <boolProp name="LoopController.continue_forever">false</boolProp>
24
+ <intProp name="LoopController.loops">-1</intProp>
25
+ </elementProp>
26
+ </kg.apc.jmeter.threads.SteppingThreadGroup>
27
+ EOF
28
+ )
29
+ )
30
+ update params
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,53 @@
1
+ module JmeterPerf
2
+ module Plugins
3
+ class TransactionsPerSecond
4
+ attr_accessor :doc
5
+ include JmeterPerf::Helpers::XmlDocumentUpdater
6
+ def initialize(params = {})
7
+ testname = params.is_a?(Array) ? "TransactionsPerSecond" : (params[:name] || "TransactionsPerSecond")
8
+ @doc = Nokogiri::XML(
9
+ JmeterPerf::Helpers::String.strip_heredoc(
10
+ <<-EOF
11
+ <kg.apc.jmeter.vizualizers.CorrectedResultCollector guiclass="kg.apc.jmeter.vizualizers.TransactionsPerSecondGui" testclass="kg.apc.jmeter.vizualizers.CorrectedResultCollector" testname="#{testname}" enabled="#{enabled(params)}">
12
+ <boolProp name="ResultCollector.error_logging">false</boolProp>
13
+ <objProp>
14
+ <name>saveConfig</name>
15
+ <value class="SampleSaveConfiguration">
16
+ <time>true</time>
17
+ <latency>true</latency>
18
+ <timestamp>true</timestamp>
19
+ <success>true</success>
20
+ <label>true</label>
21
+ <code>true</code>
22
+ <message>true</message>
23
+ <threadName>true</threadName>
24
+ <dataType>true</dataType>
25
+ <encoding>false</encoding>
26
+ <assertions>true</assertions>
27
+ <subresults>true</subresults>
28
+ <responseData>false</responseData>
29
+ <samplerData>false</samplerData>
30
+ <xml>true</xml>
31
+ <fieldNames>false</fieldNames>
32
+ <responseHeaders>false</responseHeaders>
33
+ <requestHeaders>false</requestHeaders>
34
+ <responseDataOnError>false</responseDataOnError>
35
+ <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
36
+ <assertionsResultsToSave>0</assertionsResultsToSave>
37
+ <bytes>true</bytes>
38
+ </value>
39
+ </objProp>
40
+ <stringProp name="filename"></stringProp>
41
+ <longProp name="interval_grouping">1000</longProp>
42
+ <boolProp name="graph_aggregated">false</boolProp>
43
+ <stringProp name="include_sample_labels"></stringProp>
44
+ <stringProp name="exclude_sample_labels"></stringProp>
45
+ </kg.apc.jmeter.vizualizers.CorrectedResultCollector>
46
+ EOF
47
+ )
48
+ )
49
+ update params
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,28 @@
1
+ module JmeterPerf
2
+ module Plugins
3
+ class UltimateThreadGroup
4
+ attr_accessor :doc
5
+ include JmeterPerf::Helpers::XmlDocumentUpdater
6
+ def initialize(params = {})
7
+ testname = params.is_a?(Array) ? "UltimateThreadGroup" : (params[:name] || "UltimateThreadGroup")
8
+ @doc = Nokogiri::XML(
9
+ JmeterPerf::Helpers::String.strip_heredoc(
10
+ <<-EOF
11
+ <kg.apc.jmeter.threads.UltimateThreadGroup guiclass="kg.apc.jmeter.threads.UltimateThreadGroupGui" testclass="kg.apc.jmeter.threads.UltimateThreadGroup" testname="#{testname}" enabled="true">
12
+ <collectionProp name="ultimatethreadgroupdata">
13
+ </collectionProp>
14
+ <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
15
+ <boolProp name="LoopController.continue_forever">false</boolProp>
16
+ <intProp name="LoopController.loops">-1</intProp>
17
+ </elementProp>
18
+ <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
19
+ </kg.apc.jmeter.threads.UltimateThreadGroup>
20
+ EOF
21
+ )
22
+ )
23
+
24
+ update params
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,35 @@
1
+ module JmeterPerf
2
+ module Plugins
3
+ class ThroughputShapingTimer
4
+ attr_accessor :doc
5
+ include JmeterPerf::Helpers::XmlDocumentUpdater
6
+ def initialize(params = {})
7
+ testname = params.is_a?(Array) ? "ThroughputShapingTimer" : (params[:name] || "ThroughputShapingTimer")
8
+ @doc = Nokogiri::XML(
9
+ JmeterPerf::Helpers::String.strip_heredoc(
10
+ <<-EOF
11
+ <kg.apc.jmeter.timers.VariableThroughputTimer guiclass="kg.apc.jmeter.timers.VariableThroughputTimerGui" testclass="kg.apc.jmeter.timers.VariableThroughputTimer" testname="#{testname}" enabled="true">
12
+ <collectionProp name="load_profile"/>
13
+ </kg.apc.jmeter.timers.VariableThroughputTimer>
14
+ EOF
15
+ )
16
+ )
17
+
18
+ (params.is_a?(Array) ? params : params[:steps]).each_with_index do |step, index|
19
+ @doc.at_xpath("//collectionProp") << Nokogiri::XML(
20
+ JmeterPerf::Helpers::String.strip_heredoc(
21
+ <<-EOF
22
+ <collectionProp name="step_#{index}">
23
+ <stringProp name="start_rps_#{index}">#{step[:start_rps]}</stringProp>
24
+ <stringProp name="end_rps_#{index}">#{step[:end_rps]}</stringProp>
25
+ <stringProp name="duration_sec_#{index}">#{step[:duration]}</stringProp>
26
+ </collectionProp>
27
+ EOF
28
+ )
29
+ ).children
30
+ end
31
+ update params
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,258 @@
1
+ module JmeterPerf
2
+ module Report
3
+ # Comparator performs statistical comparison between two performance reports.
4
+ # It calculates metrics like Cohen's D and T-statistic to measure the effect size
5
+ # and generates comparison reports in various formats.
6
+ class Comparator
7
+ # @return [Float] the calculated Cohen's D value
8
+ # @see https://en.wikipedia.org/wiki/Effect_size#Cohen's_d
9
+ attr_reader :cohens_d
10
+ # @return [Float] the calculated T-statistic value
11
+ # @see https://en.wikipedia.org/wiki/Student%27s_t-test
12
+ attr_reader :t_statistic
13
+ # @return [String] a human-readable rating of the comparison result
14
+ attr_reader :human_rating
15
+ # @return [String] the name of the comparison, if provided
16
+ attr_reader :name
17
+
18
+ # Effect size thresholds according to Sawilowsky's rule of thumb
19
+ EFFECT_SIZE_LIMITS = {
20
+ vsmall: 0.01, # very small
21
+ small: 0.2, # small
22
+ medium: 0.5, # medium
23
+ large: 0.8, # large
24
+ vlarge: 1.2, # very large
25
+ huge: 2.0 # huge
26
+ }
27
+
28
+ # Valid effect size directions
29
+ EFFECT_SIZE_DIRECTION = %i[positive negative both]
30
+
31
+ # Initializes a Comparator instance to compare two reports.
32
+ #
33
+ # @param base_report [Summary] the base performance report
34
+ # @param test_report [Summary] the test performance report
35
+ # @param name [String, nil] an optional name for the comparison (default: nil)
36
+ def initialize(base_report, test_report, name = nil)
37
+ @base_report = base_report
38
+ @test_report = test_report
39
+ @name = name&.gsub(/\s+/, "_")
40
+ compare_reports!
41
+ end
42
+
43
+ # Checks if the comparison passes based on Cohen's D and effect size.
44
+ # @note If no Cohen's D limit is provided, the `effect_size` threshold is used.
45
+ # @param cohens_d_limit [Float, nil] optional limit for Cohen's D (default: nil)
46
+ # @param effect_size [Symbol] the desired effect size threshold (default: :vsmall).
47
+ # See {JmeterPerf::Report::Comparator::EFFECT_SIZE_LIMITS} for options.
48
+ # @param direction [Symbol] the direction of comparison, e.g., :positive (default: :both)
49
+ # See {JmeterPerf::Report::Comparator::EFFECT_SIZE_DIRECTION} for options.
50
+ # @raise [ArgumentError] if the effect size or direction is invalid
51
+ # @return [Boolean] true if comparison meets the criteria
52
+ def pass?(cohens_d_limit: nil, effect_size: :vsmall, direction: :both)
53
+ limit = cohens_d_limit || EFFECT_SIZE_LIMITS[effect_size]
54
+ raise ArgumentError, "Invalid effect size: #{effect_size}" unless limit
55
+
56
+ raise ArgumentError, "Invalid direction: #{direction}" unless EFFECT_SIZE_DIRECTION.include?(direction)
57
+
58
+ case direction
59
+ when :positive
60
+ cohens_d >= limit
61
+ when :negative
62
+ cohens_d <= -limit
63
+ when :both
64
+ cohens_d >= limit || !(cohens_d <= -limit)
65
+ end
66
+ end
67
+
68
+ # Generates comparison reports in specified formats.
69
+ #
70
+ # @param output_dir [String] the directory for output files (default: ".")
71
+ # @param output_format [Symbol] the format for the report, e.g., :html, :csv (default: :all)
72
+ # @raise [ArgumentError] if the output format is invalid
73
+ # @return [void]
74
+ def generate_reports(output_dir: ".", output_format: :all)
75
+ generator = Generator.new(self, [@base_report, @test_report])
76
+
77
+ case output_format
78
+ when :all
79
+ generator.generate_report(File.join(output_dir, "#{@name}_comparison_report.html"), :html)
80
+ generator.generate_report(File.join(output_dir, "#{@name}_comparison_report.csv"), :csv)
81
+ when :html, :csv
82
+ generator.generate_report(File.join(output_dir, "#{@name}_comparison_report.#{output_format}"), output_format)
83
+ else
84
+ raise ArgumentError, "Invalid output format: #{output_format}"
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ # Calculates Cohen's D and T-statistic between the two reports.
91
+ #
92
+ # @return [void]
93
+ def compare_reports!
94
+ @cohens_d = calc_cohens_d(@base_report.avg, @test_report.avg, @base_report.std, @test_report.std).round(2)
95
+ @t_statistic = calc_t_statistic(
96
+ @base_report.avg,
97
+ @test_report.avg,
98
+ @base_report.std,
99
+ @test_report.std,
100
+ @test_report.total_requests
101
+ ).round(2)
102
+
103
+ set_diff_rating
104
+ end
105
+
106
+ # Calculates Cohen's D between two means with given standard deviations.
107
+ #
108
+ # @param mean1 [Float] mean of the base report
109
+ # @param mean2 [Float] mean of the test report
110
+ # @param sd1 [Float] standard deviation of the base report
111
+ # @param sd2 [Float] standard deviation of the test report
112
+ # @return [Float] calculated Cohen's D
113
+ def calc_cohens_d(mean1, mean2, sd1, sd2)
114
+ mean_diff = mean1 - mean2
115
+ pooled_sd = Math.sqrt((sd1**2 + sd2**2) / 2.0)
116
+ mean_diff / pooled_sd
117
+ end
118
+
119
+ # Calculates T-statistic between two means with given standard deviations and sample size.
120
+ #
121
+ # @param mean1 [Float] mean of the base report
122
+ # @param mean2 [Float] mean of the test report
123
+ # @param sd1 [Float] standard deviation of the base report
124
+ # @param sd2 [Float] standard deviation of the test report
125
+ # @param n2 [Integer] sample size of the test report
126
+ # @return [Float] calculated T-statistic
127
+ def calc_t_statistic(mean1, mean2, sd1, sd2, n2)
128
+ numerator = mean1 - mean2
129
+ denominator = Math.sqrt((sd1**2 + sd2**2) / n2)
130
+ numerator / denominator
131
+ end
132
+
133
+ # Sets a human-readable rating for the difference between reports.
134
+ #
135
+ # @return [void]
136
+ def set_diff_rating
137
+ s_dir = if cohens_d.positive?
138
+ "increase"
139
+ else
140
+ cohens_d.negative? ? "decrease" : "change"
141
+ end
142
+ s_mag = case cohens_d.abs
143
+ when 1.20...2.0 then "Very large"
144
+ when 0.80...1.20 then "Large"
145
+ when 0.50...0.80 then "Medium"
146
+ when 0.02...0.50 then "Small"
147
+ when 0.01...0.02 then "Very small"
148
+ when 0.0...0.01 then "Negligible"
149
+ else "Huge"
150
+ end
151
+ @human_rating = "#{s_mag} #{s_dir}"
152
+ end
153
+
154
+ # Generator is responsible for generating comparison reports in HTML and CSV formats.
155
+ class Generator
156
+ # Initializes a Generator instance to handle report generation.
157
+ #
158
+ # @param comparator [Comparator] the comparator instance
159
+ # @param reports [Array<Summary>] an array of performance reports
160
+ def initialize(comparator, reports)
161
+ @comparator = comparator
162
+ @reports = reports
163
+ end
164
+
165
+ # Generates a report in the specified format at the given path.
166
+ #
167
+ # @param output_path [String] the path to save the generated report
168
+ # @param output_format [Symbol] the format for the report, e.g., :html or :csv
169
+ # @return [void]
170
+ def generate_report(output_path, output_format)
171
+ case output_format
172
+ when :html
173
+ generate_html_report(output_path)
174
+ when :csv
175
+ generate_csv_report(output_path)
176
+ else
177
+ print_report(output_path)
178
+ end
179
+ end
180
+
181
+ # Generates an HTML report.
182
+ #
183
+ # @param output_path [String] the path to save the HTML report
184
+ # @return [void]
185
+ def generate_html_report(output_path)
186
+ template_path = File.join(__dir__, "..", "views", "report_template.html.erb")
187
+ template = File.read(template_path)
188
+ result = ERB.new(template).result(binding)
189
+ File.write(output_path, result)
190
+ end
191
+
192
+ # Generates a CSV report.
193
+ #
194
+ # @param output_path [String] the path to save the CSV report
195
+ # @return [void]
196
+ def generate_csv_report(output_path)
197
+ CSV.open(output_path, "wb") do |csv|
198
+ csv << ["Label", "Total Requests", "Total Elapsed Time", "RPM", "Errors", "Error %", "Min", "Max", "Avg", "SD", "P10", "P50", "P95"]
199
+ @reports.each_with_index do |report, index|
200
+ csv << [
201
+ (index == 0) ? "Base Metric" : "Test Metric",
202
+ report.total_requests,
203
+ report.total_elapsed_time,
204
+ sprintf("%.2f", report.rpm),
205
+ report.total_errors,
206
+ sprintf("%.2f", report.error_percentage),
207
+ report.min,
208
+ report.max,
209
+ sprintf("%.2f", report.avg),
210
+ sprintf("%.2f", report.std),
211
+ sprintf("%.2f", report.p10),
212
+ sprintf("%.2f", report.p50),
213
+ sprintf("%.2f", report.p95)
214
+ ]
215
+ end
216
+ end
217
+ end
218
+
219
+ # Prints a plain text version of the report to standard output.
220
+ #
221
+ # @param output_path [String] the path for plain text output
222
+ # @return [void]
223
+ def print_report(output_path)
224
+ report_text = "Comparison Report\n\n"
225
+ report_text << format_line(["Label", "Requests", "Errors", "Error %", "Min", "Median", "Avg", "Max", "Std", "P10", "P50", "P95"])
226
+ report_text << "-" * 90 + "\n"
227
+ @reports.each_with_index do |report, index|
228
+ report_text << format_line([
229
+ (index == 0) ? "Base Metric" : "Test Metric",
230
+ report.total_requests,
231
+ report.total_errors,
232
+ sprintf("%.2f", report.error_percentage),
233
+ report.min,
234
+ report.median,
235
+ sprintf("%.2f", report.avg),
236
+ report.max,
237
+ sprintf("%.2f", report.std),
238
+ sprintf("%.2f", report.p10),
239
+ sprintf("%.2f", report.p50),
240
+ sprintf("%.2f", report.p95)
241
+ ])
242
+ end
243
+ puts report_text
244
+ end
245
+
246
+ # Formats a line for plain text output.
247
+ #
248
+ # @param values [Array<String, Numeric>] the values to format
249
+ # @return [String] the formatted line
250
+ def format_line(values)
251
+ values.map { |v| v.to_s.ljust(10) }.join(" ") + "\n"
252
+ end
253
+ end
254
+
255
+ private_constant :Generator
256
+ end
257
+ end
258
+ end