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.
- data/.gitattributes +22 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/Gemfile +27 -0
- data/LICENSE.txt +22 -0
- data/README.md +333 -0
- data/Rakefile +6 -0
- data/bin/grid +25 -0
- data/examples/basic_assertion.rb +13 -0
- data/examples/basic_auth.rb +11 -0
- data/examples/basic_cache.rb +11 -0
- data/examples/basic_cookies.rb +11 -0
- data/examples/basic_extract.rb +10 -0
- data/examples/basic_gc_dummy_sampler.rb +10 -0
- data/examples/basic_gc_results.rb +23 -0
- data/examples/basic_google.rb +8 -0
- data/examples/basic_grid.rb +8 -0
- data/examples/basic_header.rb +19 -0
- data/examples/basic_ldap_ext.rb +16 -0
- data/examples/basic_post.rb +15 -0
- data/examples/basic_query_params.rb +8 -0
- data/examples/basic_think_time.rb +15 -0
- data/examples/basic_throughput_controller.rb +14 -0
- data/examples/basic_throughput_shaping_timer.rb +21 -0
- data/examples/etsy_login_browse.rb +64 -0
- data/lib/ruby-jmeter.rb +18 -0
- data/lib/ruby-jmeter/DSL.md +237 -0
- data/lib/ruby-jmeter/dsl.rb +419 -0
- data/lib/ruby-jmeter/dsl/access_log_sampler.rb +32 -0
- data/lib/ruby-jmeter/dsl/aggregate_graph.rb +55 -0
- data/lib/ruby-jmeter/dsl/aggregate_report.rb +55 -0
- data/lib/ruby-jmeter/dsl/ajp13_sampler.rb +41 -0
- data/lib/ruby-jmeter/dsl/assertion_results.rb +55 -0
- data/lib/ruby-jmeter/dsl/beanshell_assertion.rb +28 -0
- data/lib/ruby-jmeter/dsl/beanshell_listener.rb +28 -0
- data/lib/ruby-jmeter/dsl/beanshell_postprocessor.rb +28 -0
- data/lib/ruby-jmeter/dsl/beanshell_preprocessor.rb +28 -0
- data/lib/ruby-jmeter/dsl/beanshell_sampler.rb +28 -0
- data/lib/ruby-jmeter/dsl/beanshell_timer.rb +28 -0
- data/lib/ruby-jmeter/dsl/bsf_assertion.rb +28 -0
- data/lib/ruby-jmeter/dsl/bsf_listener.rb +28 -0
- data/lib/ruby-jmeter/dsl/bsf_postprocessor.rb +28 -0
- data/lib/ruby-jmeter/dsl/bsf_preprocessor.rb +28 -0
- data/lib/ruby-jmeter/dsl/bsf_sampler.rb +28 -0
- data/lib/ruby-jmeter/dsl/bsf_timer.rb +28 -0
- data/lib/ruby-jmeter/dsl/compare_assertion.rb +27 -0
- data/lib/ruby-jmeter/dsl/comparison_assertion_visualizer.rb +55 -0
- data/lib/ruby-jmeter/dsl/constant_throughput_timer.rb +30 -0
- data/lib/ruby-jmeter/dsl/constant_timer.rb +25 -0
- data/lib/ruby-jmeter/dsl/counter.rb +31 -0
- data/lib/ruby-jmeter/dsl/cssjquery_extractor.rb +30 -0
- data/lib/ruby-jmeter/dsl/csv_data_set_config.rb +32 -0
- data/lib/ruby-jmeter/dsl/debug_postprocessor.rb +28 -0
- data/lib/ruby-jmeter/dsl/debug_sampler.rb +27 -0
- data/lib/ruby-jmeter/dsl/distribution_graphalpha.rb +55 -0
- data/lib/ruby-jmeter/dsl/duration_assertion.rb +25 -0
- data/lib/ruby-jmeter/dsl/foreach_controller.rb +29 -0
- data/lib/ruby-jmeter/dsl/ftp_request.rb +34 -0
- data/lib/ruby-jmeter/dsl/ftp_request_defaults.rb +32 -0
- data/lib/ruby-jmeter/dsl/gaussian_random_timer.rb +26 -0
- data/lib/ruby-jmeter/dsl/generate_summary_results.rb +23 -0
- data/lib/ruby-jmeter/dsl/graph_results.rb +55 -0
- data/lib/ruby-jmeter/dsl/html_assertion.rb +30 -0
- data/lib/ruby-jmeter/dsl/html_link_parser.rb +23 -0
- data/lib/ruby-jmeter/dsl/html_parameter_mask.rb +32 -0
- data/lib/ruby-jmeter/dsl/http_authorization_manager.rb +33 -0
- data/lib/ruby-jmeter/dsl/http_cache_manager.rb +26 -0
- data/lib/ruby-jmeter/dsl/http_cookie_manager.rb +27 -0
- data/lib/ruby-jmeter/dsl/http_header_manager.rb +30 -0
- data/lib/ruby-jmeter/dsl/http_request.rb +41 -0
- data/lib/ruby-jmeter/dsl/http_request_defaults.rb +44 -0
- data/lib/ruby-jmeter/dsl/http_url_rewriting_modifier.rb +29 -0
- data/lib/ruby-jmeter/dsl/if_controller.rb +27 -0
- data/lib/ruby-jmeter/dsl/include_controller.rb +25 -0
- data/lib/ruby-jmeter/dsl/java_request.rb +69 -0
- data/lib/ruby-jmeter/dsl/java_request_defaults.rb +69 -0
- data/lib/ruby-jmeter/dsl/jdbc_connection_configuration.rb +37 -0
- data/lib/ruby-jmeter/dsl/jdbc_postprocessor.rb +31 -0
- data/lib/ruby-jmeter/dsl/jdbc_preprocessor.rb +31 -0
- data/lib/ruby-jmeter/dsl/jdbc_request.rb +31 -0
- data/lib/ruby-jmeter/dsl/jms_pointtopoint.rb +40 -0
- data/lib/ruby-jmeter/dsl/jms_publisher.rb +41 -0
- data/lib/ruby-jmeter/dsl/jms_subscriber.rb +35 -0
- data/lib/ruby-jmeter/dsl/jsr223_assertion.rb +29 -0
- data/lib/ruby-jmeter/dsl/jsr223_listener.rb +29 -0
- data/lib/ruby-jmeter/dsl/jsr223_postprocessor.rb +29 -0
- data/lib/ruby-jmeter/dsl/jsr223_preprocessor.rb +29 -0
- data/lib/ruby-jmeter/dsl/jsr223_sampler.rb +29 -0
- data/lib/ruby-jmeter/dsl/jsr223_timer.rb +29 -0
- data/lib/ruby-jmeter/dsl/junit_request.rb +37 -0
- data/lib/ruby-jmeter/dsl/keystore_configuration.rb +27 -0
- data/lib/ruby-jmeter/dsl/ldap_extended_request.rb +42 -0
- data/lib/ruby-jmeter/dsl/ldap_extended_request_defaults.rb +42 -0
- data/lib/ruby-jmeter/dsl/ldap_request.rb +35 -0
- data/lib/ruby-jmeter/dsl/ldap_request_defaults.rb +40 -0
- data/lib/ruby-jmeter/dsl/login_config_element.rb +26 -0
- data/lib/ruby-jmeter/dsl/loop_controller.rb +26 -0
- data/lib/ruby-jmeter/dsl/mail_reader_sampler.rb +37 -0
- data/lib/ruby-jmeter/dsl/mailer_visualizer.rb +64 -0
- data/lib/ruby-jmeter/dsl/md5hex_assertion.rb +25 -0
- data/lib/ruby-jmeter/dsl/module_controller.rb +23 -0
- data/lib/ruby-jmeter/dsl/monitor_results.rb +55 -0
- data/lib/ruby-jmeter/dsl/once_only_controller.rb +23 -0
- data/lib/ruby-jmeter/dsl/os_process_sampler.rb +34 -0
- data/lib/ruby-jmeter/dsl/poisson_random_timer.rb +26 -0
- data/lib/ruby-jmeter/dsl/random_controller.rb +25 -0
- data/lib/ruby-jmeter/dsl/random_order_controller.rb +23 -0
- data/lib/ruby-jmeter/dsl/random_variable.rb +30 -0
- data/lib/ruby-jmeter/dsl/recording_controller.rb +23 -0
- data/lib/ruby-jmeter/dsl/regex_user_parameters.rb +27 -0
- data/lib/ruby-jmeter/dsl/regular_expression_extractor.rb +31 -0
- data/lib/ruby-jmeter/dsl/response_assertion.rb +31 -0
- data/lib/ruby-jmeter/dsl/response_time_graph.rb +55 -0
- data/lib/ruby-jmeter/dsl/result_status_action_handler.rb +25 -0
- data/lib/ruby-jmeter/dsl/runtime_controller.rb +25 -0
- data/lib/ruby-jmeter/dsl/save_responses_to_a_file.rb +29 -0
- data/lib/ruby-jmeter/dsl/simple_config_element.rb +23 -0
- data/lib/ruby-jmeter/dsl/simple_controller.rb +23 -0
- data/lib/ruby-jmeter/dsl/simple_data_writer.rb +55 -0
- data/lib/ruby-jmeter/dsl/smime_assertion.rb +35 -0
- data/lib/ruby-jmeter/dsl/smtp_sampler.rb +51 -0
- data/lib/ruby-jmeter/dsl/soapxmlrpc_request.rb +33 -0
- data/lib/ruby-jmeter/dsl/spline_visualizer.rb +55 -0
- data/lib/ruby-jmeter/dsl/summary_report.rb +55 -0
- data/lib/ruby-jmeter/dsl/switch_controller.rb +25 -0
- data/lib/ruby-jmeter/dsl/synchronizing_timer.rb +25 -0
- data/lib/ruby-jmeter/dsl/tcp_sampler.rb +33 -0
- data/lib/ruby-jmeter/dsl/tcp_sampler_config.rb +31 -0
- data/lib/ruby-jmeter/dsl/test_action.rb +27 -0
- data/lib/ruby-jmeter/dsl/test_plan.rb +31 -0
- data/lib/ruby-jmeter/dsl/thread_group.rb +36 -0
- data/lib/ruby-jmeter/dsl/throughput_controller.rb +32 -0
- data/lib/ruby-jmeter/dsl/transaction_controller.rb +26 -0
- data/lib/ruby-jmeter/dsl/uniform_random_timer.rb +26 -0
- data/lib/ruby-jmeter/dsl/user_defined_variables.rb +32 -0
- data/lib/ruby-jmeter/dsl/user_parameters.rb +29 -0
- data/lib/ruby-jmeter/dsl/view_results_in_table.rb +55 -0
- data/lib/ruby-jmeter/dsl/view_results_tree.rb +55 -0
- data/lib/ruby-jmeter/dsl/while_controller.rb +25 -0
- data/lib/ruby-jmeter/dsl/xml_assertion.rb +23 -0
- data/lib/ruby-jmeter/dsl/xml_schema_assertion.rb +25 -0
- data/lib/ruby-jmeter/dsl/xpath_assertion.rb +30 -0
- data/lib/ruby-jmeter/dsl/xpath_extractor.rb +30 -0
- data/lib/ruby-jmeter/helpers/fallback_content_proxy.rb +54 -0
- data/lib/ruby-jmeter/helpers/helper.rb +41 -0
- data/lib/ruby-jmeter/helpers/jmeter.properties +28 -0
- data/lib/ruby-jmeter/helpers/logger-colors.rb +48 -0
- data/lib/ruby-jmeter/helpers/parser.rb +106 -0
- data/lib/ruby-jmeter/helpers/strip-heredoc.rb +5 -0
- data/lib/ruby-jmeter/helpers/user-agents.rb +27 -0
- data/lib/ruby-jmeter/idl.rb +70 -0
- data/lib/ruby-jmeter/idl.xml +1513 -0
- data/lib/ruby-jmeter/plugins/gc_console_status_logger.rb +14 -0
- data/lib/ruby-jmeter/plugins/gc_dummy_sampler.rb +23 -0
- data/lib/ruby-jmeter/plugins/gc_latencies_over_time.rb +48 -0
- data/lib/ruby-jmeter/plugins/gc_response_codes_per_second.rb +48 -0
- data/lib/ruby-jmeter/plugins/gc_response_times_distribution.rb +47 -0
- data/lib/ruby-jmeter/plugins/gc_response_times_over_time.rb +48 -0
- data/lib/ruby-jmeter/plugins/gc_response_times_percentiles.rb +48 -0
- data/lib/ruby-jmeter/plugins/gc_transactions_per_second.rb +48 -0
- data/lib/ruby-jmeter/plugins/gc_variable_throughput_timer.rb +26 -0
- data/lib/ruby-jmeter/version.rb +3 -0
- data/ruby-jmeter.gemspec +22 -0
- data/spec/dsl_spec.rb +491 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/stub.rb +31 -0
- 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
|
data/ruby-jmeter.gemspec
ADDED
|
@@ -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
|