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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +19 -0
- data/.standard.yml +4 -0
- data/CHANGELOG.md +18 -0
- data/DSL.md +235 -0
- data/README.md +24 -0
- data/Rakefile +12 -0
- data/example/Gemfile +39 -0
- data/example/Gemfile.lock +232 -0
- data/example/README.md +3 -0
- data/example/Rakefile +6 -0
- data/example/app/controllers/application_controller.rb +2 -0
- data/example/app/controllers/test_controller.rb +15 -0
- data/example/bin/bundle +109 -0
- data/example/bin/docker-entrypoint +8 -0
- data/example/bin/rails +4 -0
- data/example/bin/rake +4 -0
- data/example/bin/setup +33 -0
- data/example/config/application.rb +44 -0
- data/example/config/boot.rb +3 -0
- data/example/config/credentials.yml.enc +1 -0
- data/example/config/database.yml +25 -0
- data/example/config/environment.rb +5 -0
- data/example/config/environments/development.rb +64 -0
- data/example/config/environments/production.rb +82 -0
- data/example/config/environments/test.rb +61 -0
- data/example/config/initializers/cors.rb +16 -0
- data/example/config/initializers/filter_parameter_logging.rb +8 -0
- data/example/config/initializers/inflections.rb +16 -0
- data/example/config/locales/en.yml +31 -0
- data/example/config/puma.rb +35 -0
- data/example/config/routes.rb +5 -0
- data/example/config.ru +7 -0
- data/example/fast.log +49 -0
- data/example/jmeter.log +28 -0
- data/example/lib/tasks/test.rake +40 -0
- data/example/log/.keep +0 -0
- data/example/public/robots.txt +1 -0
- data/example/random.log +49 -0
- data/example/slow.log +49 -0
- data/example/vendor/.keep +0 -0
- data/lib/Rakefile +4 -0
- data/lib/jmeter_perf/dsl/access_log_sampler.rb +38 -0
- data/lib/jmeter_perf/dsl/aggregate_graph.rb +61 -0
- data/lib/jmeter_perf/dsl/aggregate_report.rb +61 -0
- data/lib/jmeter_perf/dsl/ajp13_sampler.rb +47 -0
- data/lib/jmeter_perf/dsl/assertion_results.rb +61 -0
- data/lib/jmeter_perf/dsl/bean_shell_assertion.rb +34 -0
- data/lib/jmeter_perf/dsl/bean_shell_listener.rb +34 -0
- data/lib/jmeter_perf/dsl/bean_shell_postprocessor.rb +34 -0
- data/lib/jmeter_perf/dsl/bean_shell_preprocessor.rb +34 -0
- data/lib/jmeter_perf/dsl/bean_shell_sampler.rb +34 -0
- data/lib/jmeter_perf/dsl/bean_shell_timer.rb +34 -0
- data/lib/jmeter_perf/dsl/bsf_assertion.rb +34 -0
- data/lib/jmeter_perf/dsl/bsf_listener.rb +34 -0
- data/lib/jmeter_perf/dsl/bsf_postprocessor.rb +34 -0
- data/lib/jmeter_perf/dsl/bsf_preprocessor.rb +34 -0
- data/lib/jmeter_perf/dsl/bsf_sampler.rb +34 -0
- data/lib/jmeter_perf/dsl/bsf_timer.rb +34 -0
- data/lib/jmeter_perf/dsl/compare_assertion.rb +33 -0
- data/lib/jmeter_perf/dsl/comparison_assertion_visualizer.rb +61 -0
- data/lib/jmeter_perf/dsl/constant_throughput_timer.rb +32 -0
- data/lib/jmeter_perf/dsl/constant_timer.rb +31 -0
- data/lib/jmeter_perf/dsl/counter.rb +37 -0
- data/lib/jmeter_perf/dsl/css_jquery_extractor.rb +37 -0
- data/lib/jmeter_perf/dsl/csv_data_set_config.rb +39 -0
- data/lib/jmeter_perf/dsl/debug_postprocessor.rb +34 -0
- data/lib/jmeter_perf/dsl/debug_sampler.rb +33 -0
- data/lib/jmeter_perf/dsl/distribution_graphalpha.rb +61 -0
- data/lib/jmeter_perf/dsl/duration_assertion.rb +31 -0
- data/lib/jmeter_perf/dsl/for_each_controller.rb +33 -0
- data/lib/jmeter_perf/dsl/ftp_request.rb +40 -0
- data/lib/jmeter_perf/dsl/ftp_request_defaults.rb +38 -0
- data/lib/jmeter_perf/dsl/gaussian_random_timer.rb +32 -0
- data/lib/jmeter_perf/dsl/generate_summary_results.rb +29 -0
- data/lib/jmeter_perf/dsl/graph_results.rb +61 -0
- data/lib/jmeter_perf/dsl/html_assertion.rb +36 -0
- data/lib/jmeter_perf/dsl/html_link_parser.rb +29 -0
- data/lib/jmeter_perf/dsl/html_parameter_mask.rb +38 -0
- data/lib/jmeter_perf/dsl/http_authorization_manager.rb +39 -0
- data/lib/jmeter_perf/dsl/http_cache_manager.rb +32 -0
- data/lib/jmeter_perf/dsl/http_cookie_manager.rb +34 -0
- data/lib/jmeter_perf/dsl/http_header_manager.rb +36 -0
- data/lib/jmeter_perf/dsl/http_request.rb +47 -0
- data/lib/jmeter_perf/dsl/http_request_defaults.rb +53 -0
- data/lib/jmeter_perf/dsl/http_url_rewriting_modifier.rb +36 -0
- data/lib/jmeter_perf/dsl/if_controller.rb +33 -0
- data/lib/jmeter_perf/dsl/include_controller.rb +31 -0
- data/lib/jmeter_perf/dsl/j_unit_request.rb +43 -0
- data/lib/jmeter_perf/dsl/java_request.rb +75 -0
- data/lib/jmeter_perf/dsl/java_request_defaults.rb +75 -0
- data/lib/jmeter_perf/dsl/jdbc_connection_configuration.rb +43 -0
- data/lib/jmeter_perf/dsl/jdbc_postprocessor.rb +39 -0
- data/lib/jmeter_perf/dsl/jdbc_preprocessor.rb +39 -0
- data/lib/jmeter_perf/dsl/jdbc_request.rb +39 -0
- data/lib/jmeter_perf/dsl/jms_pointto_point.rb +47 -0
- data/lib/jmeter_perf/dsl/jms_publisher.rb +49 -0
- data/lib/jmeter_perf/dsl/jms_subscriber.rb +41 -0
- data/lib/jmeter_perf/dsl/json_path_postprocessor.rb +33 -0
- data/lib/jmeter_perf/dsl/jsr223_assertion.rb +35 -0
- data/lib/jmeter_perf/dsl/jsr223_listener.rb +35 -0
- data/lib/jmeter_perf/dsl/jsr223_postprocessor.rb +35 -0
- data/lib/jmeter_perf/dsl/jsr223_preprocessor.rb +35 -0
- data/lib/jmeter_perf/dsl/jsr223_sampler.rb +35 -0
- data/lib/jmeter_perf/dsl/jsr223_timer.rb +35 -0
- data/lib/jmeter_perf/dsl/keystore_configuration.rb +34 -0
- data/lib/jmeter_perf/dsl/ldap_extended_request.rb +48 -0
- data/lib/jmeter_perf/dsl/ldap_extended_request_defaults.rb +48 -0
- data/lib/jmeter_perf/dsl/ldap_request.rb +41 -0
- data/lib/jmeter_perf/dsl/ldap_request_defaults.rb +45 -0
- data/lib/jmeter_perf/dsl/login_config_element.rb +32 -0
- data/lib/jmeter_perf/dsl/loop_controller.rb +32 -0
- data/lib/jmeter_perf/dsl/mail_reader_sampler.rb +43 -0
- data/lib/jmeter_perf/dsl/mailer_visualizer.rb +70 -0
- data/lib/jmeter_perf/dsl/md5_hex_assertion.rb +31 -0
- data/lib/jmeter_perf/dsl/module_controller.rb +31 -0
- data/lib/jmeter_perf/dsl/monitor_results.rb +61 -0
- data/lib/jmeter_perf/dsl/once_only_controller.rb +29 -0
- data/lib/jmeter_perf/dsl/os_process_sampler.rb +40 -0
- data/lib/jmeter_perf/dsl/poisson_random_timer.rb +32 -0
- data/lib/jmeter_perf/dsl/random_controller.rb +31 -0
- data/lib/jmeter_perf/dsl/random_order_controller.rb +29 -0
- data/lib/jmeter_perf/dsl/random_variable.rb +36 -0
- data/lib/jmeter_perf/dsl/recording_controller.rb +29 -0
- data/lib/jmeter_perf/dsl/reg_ex_user_parameters.rb +33 -0
- data/lib/jmeter_perf/dsl/regular_expression_extractor.rb +38 -0
- data/lib/jmeter_perf/dsl/response_assertion.rb +37 -0
- data/lib/jmeter_perf/dsl/response_time_graph.rb +61 -0
- data/lib/jmeter_perf/dsl/result_status_action_handler.rb +31 -0
- data/lib/jmeter_perf/dsl/runtime_controller.rb +31 -0
- data/lib/jmeter_perf/dsl/save_responses_to_a_file.rb +35 -0
- data/lib/jmeter_perf/dsl/simple_config_element.rb +29 -0
- data/lib/jmeter_perf/dsl/simple_controller.rb +29 -0
- data/lib/jmeter_perf/dsl/simple_data_writer.rb +61 -0
- data/lib/jmeter_perf/dsl/smime_assertion.rb +41 -0
- data/lib/jmeter_perf/dsl/smtp_sampler.rb +57 -0
- data/lib/jmeter_perf/dsl/soap_xml_rpc_request.rb +39 -0
- data/lib/jmeter_perf/dsl/spline_visualizer.rb +61 -0
- data/lib/jmeter_perf/dsl/summary_report.rb +61 -0
- data/lib/jmeter_perf/dsl/switch_controller.rb +31 -0
- data/lib/jmeter_perf/dsl/synchronizing_timer.rb +32 -0
- data/lib/jmeter_perf/dsl/tcp_sampler.rb +39 -0
- data/lib/jmeter_perf/dsl/tcp_sampler_config.rb +37 -0
- data/lib/jmeter_perf/dsl/test_action.rb +33 -0
- data/lib/jmeter_perf/dsl/test_fragment.rb +29 -0
- data/lib/jmeter_perf/dsl/test_plan.rb +37 -0
- data/lib/jmeter_perf/dsl/thread_group.rb +43 -0
- data/lib/jmeter_perf/dsl/throughput_controller.rb +38 -0
- data/lib/jmeter_perf/dsl/transaction_controller.rb +32 -0
- data/lib/jmeter_perf/dsl/uniform_random_timer.rb +32 -0
- data/lib/jmeter_perf/dsl/user_defined_variables.rb +39 -0
- data/lib/jmeter_perf/dsl/user_parameters.rb +36 -0
- data/lib/jmeter_perf/dsl/view_results_in_table.rb +61 -0
- data/lib/jmeter_perf/dsl/view_results_tree.rb +61 -0
- data/lib/jmeter_perf/dsl/while_controller.rb +31 -0
- data/lib/jmeter_perf/dsl/x_path_assertion.rb +37 -0
- data/lib/jmeter_perf/dsl/x_path_extractor.rb +37 -0
- data/lib/jmeter_perf/dsl/xml_assertion.rb +29 -0
- data/lib/jmeter_perf/dsl/xml_schema_assertion.rb +31 -0
- data/lib/jmeter_perf/extend/assertions/response_assertion.rb +38 -0
- data/lib/jmeter_perf/extend/config_elements/header_manager.rb +13 -0
- data/lib/jmeter_perf/extend/config_elements/http_cache_manager.rb +12 -0
- data/lib/jmeter_perf/extend/config_elements/http_cookie_manager.rb +39 -0
- data/lib/jmeter_perf/extend/config_elements/http_request_defaults.rb +55 -0
- data/lib/jmeter_perf/extend/config_elements/user_defined_variables.rb +13 -0
- data/lib/jmeter_perf/extend/config_elements/user_parameters.rb +31 -0
- data/lib/jmeter_perf/extend/controllers/foreach_controller.rb +31 -0
- data/lib/jmeter_perf/extend/controllers/loop_controller.rb +11 -0
- data/lib/jmeter_perf/extend/controllers/module_controller.rb +26 -0
- data/lib/jmeter_perf/extend/controllers/throughput_controller.rb +15 -0
- data/lib/jmeter_perf/extend/controllers/transaction_controller.rb +14 -0
- data/lib/jmeter_perf/extend/misc/exists.rb +13 -0
- data/lib/jmeter_perf/extend/misc/rsync.rb +24 -0
- data/lib/jmeter_perf/extend/misc/uuid.rb +12 -0
- data/lib/jmeter_perf/extend/misc/with_helpers.rb +27 -0
- data/lib/jmeter_perf/extend/plugins/jmeter_plugins.rb +124 -0
- data/lib/jmeter_perf/extend/processors/extract.rb +27 -0
- data/lib/jmeter_perf/extend/processors/regular_expression_extractor.rb +27 -0
- data/lib/jmeter_perf/extend/samplers/http_request.rb +66 -0
- data/lib/jmeter_perf/extend/samplers/jms_pointtopoint.rb +23 -0
- data/lib/jmeter_perf/extend/samplers/soapxmlrpc_request.rb +10 -0
- data/lib/jmeter_perf/extend/threads/thread_group.rb +19 -0
- data/lib/jmeter_perf/extend/timers/constant_throughput_timer.rb +11 -0
- data/lib/jmeter_perf/extend/timers/random_timer.rb +14 -0
- data/lib/jmeter_perf/helpers/dsl_generator.rb +157 -0
- data/lib/jmeter_perf/helpers/fallback_content_proxy.rb +96 -0
- data/lib/jmeter_perf/helpers/helper.rb +63 -0
- data/lib/jmeter_perf/helpers/parser.rb +143 -0
- data/lib/jmeter_perf/helpers/running_statistics.rb +62 -0
- data/lib/jmeter_perf/helpers/string.rb +60 -0
- data/lib/jmeter_perf/helpers/user-agents.rb +42 -0
- data/lib/jmeter_perf/plugins/active_threads_over_time.rb +59 -0
- data/lib/jmeter_perf/plugins/composite_graph.rb +77 -0
- data/lib/jmeter_perf/plugins/console_status_logger.rb +19 -0
- data/lib/jmeter_perf/plugins/dummy_sampler.rb +30 -0
- data/lib/jmeter_perf/plugins/jmx_collector.rb +74 -0
- data/lib/jmeter_perf/plugins/json_path_assertion.rb +23 -0
- data/lib/jmeter_perf/plugins/json_path_extractor.rb +22 -0
- data/lib/jmeter_perf/plugins/latencies_over_time.rb +53 -0
- data/lib/jmeter_perf/plugins/loadosophia_uploader.rb +66 -0
- data/lib/jmeter_perf/plugins/perfmon_collector.rb +87 -0
- data/lib/jmeter_perf/plugins/redis_data_set.rb +43 -0
- data/lib/jmeter_perf/plugins/response_codes_per_second.rb +53 -0
- data/lib/jmeter_perf/plugins/response_times_distribution.rb +53 -0
- data/lib/jmeter_perf/plugins/response_times_over_time.rb +53 -0
- data/lib/jmeter_perf/plugins/response_times_percentiles.rb +54 -0
- data/lib/jmeter_perf/plugins/stepping_thread_group.rb +34 -0
- data/lib/jmeter_perf/plugins/transactions_per_second.rb +53 -0
- data/lib/jmeter_perf/plugins/ultimate_thread_group.rb +28 -0
- data/lib/jmeter_perf/plugins/variable_throughput_timer.rb +35 -0
- data/lib/jmeter_perf/report/comparator.rb +258 -0
- data/lib/jmeter_perf/report/summary.rb +268 -0
- data/lib/jmeter_perf/tasks/dsl.rake +19 -0
- data/lib/jmeter_perf/version.rb +5 -0
- data/lib/jmeter_perf/views/report_template.html.erb +114 -0
- data/lib/jmeter_perf.rb +183 -0
- data/lib/specifications/idl.xml +1494 -0
- data/sig/jmeter_perf.rbs +195 -0
- data/sorbet/config +5 -0
- data/sorbet/rbi/annotations/.gitattributes +1 -0
- data/sorbet/rbi/annotations/rainbow.rbi +269 -0
- data/sorbet/rbi/gems/.gitattributes +1 -0
- data/sorbet/rbi/gems/ast@2.4.2.rbi +585 -0
- data/sorbet/rbi/gems/bump@0.10.0.rbi +169 -0
- data/sorbet/rbi/gems/byebug@11.1.3.rbi +3607 -0
- data/sorbet/rbi/gems/coderay@1.1.3.rbi +3427 -0
- data/sorbet/rbi/gems/diff-lcs@1.5.1.rbi +1131 -0
- data/sorbet/rbi/gems/docile@1.4.1.rbi +377 -0
- data/sorbet/rbi/gems/erubi@1.13.0.rbi +150 -0
- data/sorbet/rbi/gems/json@2.7.2.rbi +1562 -0
- data/sorbet/rbi/gems/language_server-protocol@3.17.0.3.rbi +14238 -0
- data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +240 -0
- data/sorbet/rbi/gems/method_source@1.1.0.rbi +304 -0
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
- data/sorbet/rbi/gems/nokogiri@1.16.7.rbi +7311 -0
- data/sorbet/rbi/gems/parallel@1.26.3.rbi +291 -0
- data/sorbet/rbi/gems/parser@3.3.5.0.rbi +5519 -0
- data/sorbet/rbi/gems/prism@1.2.0.rbi +39085 -0
- data/sorbet/rbi/gems/pry-byebug@3.10.1.rbi +1151 -0
- data/sorbet/rbi/gems/pry@0.14.2.rbi +10076 -0
- data/sorbet/rbi/gems/racc@1.8.1.rbi +162 -0
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +403 -0
- data/sorbet/rbi/gems/rake@13.2.1.rbi +3074 -0
- data/sorbet/rbi/gems/rbi@0.2.1.rbi +4535 -0
- data/sorbet/rbi/gems/rbtree3@0.7.1.rbi +9 -0
- data/sorbet/rbi/gems/regexp_parser@2.9.2.rbi +3772 -0
- data/sorbet/rbi/gems/rexml@3.3.8.rbi +4858 -0
- data/sorbet/rbi/gems/rspec-core@3.13.1.rbi +11132 -0
- data/sorbet/rbi/gems/rspec-expectations@3.13.3.rbi +8183 -0
- data/sorbet/rbi/gems/rspec-mocks@3.13.1.rbi +5341 -0
- data/sorbet/rbi/gems/rspec-support@3.13.1.rbi +1630 -0
- data/sorbet/rbi/gems/rspec@3.13.0.rbi +83 -0
- data/sorbet/rbi/gems/rubocop-ast@1.32.3.rbi +7054 -0
- data/sorbet/rbi/gems/rubocop-performance@1.21.1.rbi +9 -0
- data/sorbet/rbi/gems/rubocop@1.65.1.rbi +58182 -0
- data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1318 -0
- data/sorbet/rbi/gems/simplecov-html@0.13.1.rbi +225 -0
- data/sorbet/rbi/gems/simplecov@0.22.0.rbi +2149 -0
- data/sorbet/rbi/gems/simplecov_json_formatter@0.1.4.rbi +9 -0
- data/sorbet/rbi/gems/spoom@1.5.0.rbi +4932 -0
- data/sorbet/rbi/gems/standard-custom@1.0.2.rbi +9 -0
- data/sorbet/rbi/gems/standard-performance@1.4.0.rbi +9 -0
- data/sorbet/rbi/gems/standard@1.40.0.rbi +926 -0
- data/sorbet/rbi/gems/tapioca@0.16.3.rbi +3596 -0
- data/sorbet/rbi/gems/tdigest@0.2.1.rbi +170 -0
- data/sorbet/rbi/gems/thor@1.3.2.rbi +4378 -0
- data/sorbet/rbi/gems/unicode-display_width@2.6.0.rbi +66 -0
- data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
- data/sorbet/rbi/gems/yard@0.9.37.rbi +18379 -0
- data/sorbet/rbi/todo.rbi +31 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +15 -0
- data/tasks/dsl.rake +22 -0
- 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
|