ruby-jmeter 2.13.7 → 2.13.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2fad51ef27a7e3737b320fbb418db4772ffe6300
4
- data.tar.gz: 6b266bfbd9507a0b8f08259d80a110923ef74e0d
3
+ metadata.gz: 01ab5cb50b02e20695b64b2e420a551117a9af6b
4
+ data.tar.gz: 4a844acbf379fd95132e773fd46b5dbdb2d317d3
5
5
  SHA512:
6
- metadata.gz: 590dadd09d7a91119e24acb35af182950e127f4f47be0c4207c8b5b9a2af0655ad00b51ffaab2fa8035f4b034dc021c4666b96d861c941f100c141018aa3a386
7
- data.tar.gz: 4b8110856c259925912c3b471f629656000539295ad0d6e137f79ab37419ab6a40d9798ae6144605c2d590cd429706e381c5f27c5ec454d00defa85fbad00ad8
6
+ metadata.gz: e242b7f6a1f74a4c0adbff263ff5a2d5ef7950aaee5218085bca02e632f6c8bae13ee62cdb2347a6b1a8a8495f09e65c604c26ff9b25c0faf07da6e10a6d01e6
7
+ data.tar.gz: 0dc1ce59b26da2c80fa14de8db4ad5db04a57cd2fb52104a1cf5e5230904bb5a08303924154e5d491ca1b4cf9b5cfbf2bd18a4c2077a48e4c99e018fffb91b06
data/README.md CHANGED
@@ -303,7 +303,7 @@ This method takes 2 parameters: the constant delay, and an optional variable del
303
303
  # constant delay of 3 seconds
304
304
  think_time 3000
305
305
  # constant delay of 1 seconds with variance up to 6 seconds.
306
- random_timer 1000,5000
306
+ random_timer 1000, 6000
307
307
  ```
308
308
 
309
309
  ### Response Extractor
@@ -381,3 +381,78 @@ This work is being sponsored by Flood IO. Get in touch with us if you'd like to
381
381
  4. Commit your changes (`git commit -am 'Add some feature'`)
382
382
  5. Push to the branch (`git push origin my-new-feature`)
383
383
  6. Create new Pull Request
384
+
385
+ ### IDL
386
+
387
+ We use an interface description language (IDL) as a bridge between JMeter's components expressed as XML in a `.jmx` test plan to Ruby's DSL objects in this repository.
388
+
389
+ To automate this `lib/ruby-jmeter/idl.rb` can be executed from the command line which will read from `lib/ruby-jmeter/idl.xml` and output to `lib/ruby-jmeter/dsl`
390
+
391
+ For example:
392
+
393
+ ```sh
394
+ flood/ruby-jmeter - [master●] » ruby lib/ruby-jmeter/idl.rb
395
+ flood/ruby-jmeter - [master●] » git status
396
+ On branch master
397
+ Your branch is up-to-date with 'origin/master'.
398
+ Changes not staged for commit:
399
+ (use "git add <file>..." to update what will be committed)
400
+ (use "git checkout -- <file>..." to discard changes in working directory)
401
+
402
+ modified: lib/ruby-jmeter/DSL.md
403
+ modified: lib/ruby-jmeter/dsl/foreach_controller.rb
404
+ modified: lib/ruby-jmeter/dsl/http_request.rb
405
+ modified: lib/ruby-jmeter/dsl/http_request_defaults.rb
406
+ modified: lib/ruby-jmeter/dsl/regular_expression_extractor.rb
407
+ modified: lib/ruby-jmeter/dsl/response_assertion.rb
408
+ modified: lib/ruby-jmeter/dsl/test_fragment.rb
409
+ modified: lib/ruby-jmeter/dsl/user_parameters.rb
410
+ ```
411
+
412
+ You **should never manually update** code in `lib/ruby-jmeter/dsl` as this is automatically overwritten whenever we run the IDL script. As new components / plugins are added, or major versions of JMeter are updated, we open `lib/ruby-jmeter/idl.xml` in the JMeter UI with those updates prior to running the IDL script. This makes updating between versions more easy.
413
+
414
+ ### DSL
415
+
416
+ Much of the behaviour of the gem is defined in `lib/ruby-jmeter/dsl.rb` which is where you should be updating code. This is now a very long module and in much need of refactoring. PR's are welcomed.
417
+
418
+ ### Plugins
419
+
420
+ Some custom code has been contributed particularly for support of JMeter plugins. These are not included in the IDL and as such should be added to `lib/ruby-jmeter/plugins`. Please follow some of the other examples.
421
+
422
+ ### Bundler
423
+
424
+ We recommend using the Ruby gem bundle to manage your dependencies. Typical setup would be:
425
+
426
+
427
+ ```sh
428
+ gem install bundler
429
+ cd <your local clone>
430
+ bundle install
431
+ ```
432
+
433
+ Then you can run any rake / test tasks with the prefix `bundle exec`
434
+
435
+ ### Tests
436
+
437
+ If contributing please add an appropriate test. See `spec/dsl_spec.rb` for examples. Tests can be run from the command line as follows:
438
+
439
+ $ bundle exec rspec
440
+
441
+ ### Examples
442
+
443
+ It is often useful to add an appropriate example for other users and for testing your changes locally with the JMeter UI. See `examples` for different types of examples. To let your examples work locally from your own changes / commits simply prefix the examples with:
444
+
445
+ ```ruby
446
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
447
+ ```
448
+
449
+ $ flood/ruby-jmeter - [master●] » ruby examples/basic_assertion.rb
450
+ W, [2015-10-17T19:31:12.021004 #33216] WARN -- : Test executing locally ...
451
+
452
+ Note: most of the examples assume the JMeter binary is installed in `/usr/share/jmeter-2.13/bin/` however you can modify this in your example to something that suits your installation e.g.:
453
+
454
+
455
+ ```ruby
456
+ ...
457
+ end.run(path: 'C/Program Files/JMeter-2.13/bin/', gui: true)
458
+ ```
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'ruby-jmeter'
3
+
4
+ test do
5
+ threads count: 1, loop: 1 do
6
+ visit 'https://api.github.com/orgs/flood-io/repos' do
7
+ assert json: '.name', value: 'ruby-jmeter'
8
+ end
9
+ end
10
+ end.run(path: '/usr/share/jmeter-2.13/bin/', gui: true)
@@ -20,7 +20,8 @@ test do
20
20
  # You need perfmon agent running
21
21
  # http://jmeter-plugins.org/wiki/PerfMonAgent/
22
22
  #
23
- perfmon_collector 'Perfmon Metrics Collector', [
23
+ perfmon_collector name: 'Perfmon Metrics Collector',
24
+ nodes: [
24
25
  {
25
26
  server: 'localhost',
26
27
  port: 4444,
@@ -401,13 +401,7 @@ module RubyJmeter
401
401
  def response_assertion(params = {}, &block)
402
402
  params[:test_type] = parse_test_type(params)
403
403
  params['0'] = params.values.first
404
- node = RubyJmeter::ResponseAssertion.new(params)
405
- if params[:variable] then
406
- params['Scope.variable'] = params[:variable]
407
- node.doc.xpath("//stringProp[@name='Assertion.scope']").first.content = 'variable'
408
- end
409
- node.doc.xpath("//stringProp[@name='Assertion.scope']").remove if
410
- params[:scope] == 'main' || params['scope'] == 'main'
404
+ node = params[:json] ? json_path_assertion(params) : assertion(params)
411
405
  attach_node(node, &block)
412
406
  end
413
407
 
@@ -511,8 +505,8 @@ module RubyJmeter
511
505
 
512
506
  alias_method :active_threads, :active_threads_over_time
513
507
 
514
- def perfmon_collector(name, params = {}, filename="perfMon.jtl", &block)
515
- node = RubyJmeter::Plugins::PerfmonCollector.new(name, params, filename)
508
+ def perfmon_collector(params = {}, &block)
509
+ node = RubyJmeter::Plugins::PerfmonCollector.new(params)
516
510
  attach_node(node, &block)
517
511
  end
518
512
 
@@ -672,6 +666,25 @@ module RubyJmeter
672
666
  @log.level = Logger::DEBUG
673
667
  @log
674
668
  end
669
+
670
+ def json_path_assertion(params)
671
+ params[:EXPECTED_VALUE] = params[:value]
672
+ params[:JSON_PATH] = params[:json]
673
+ RubyJmeter::Plugins::JsonPathAssertion.new(params)
674
+ end
675
+
676
+ def assertion(params)
677
+ RubyJmeter::ResponseAssertion.new(params).tap do |node|
678
+ if params[:variable]
679
+ params['Scope.variable'] = params[:variable]
680
+ node.doc.xpath("//stringProp[@name='Assertion.scope']").first.content = 'variable'
681
+ end
682
+
683
+ if params[:scope] == 'main' || params['scope'] == 'main'
684
+ node.doc.xpath("//stringProp[@name='Assertion.scope']").remove
685
+ end
686
+ end
687
+ end
675
688
  end
676
689
  end
677
690
 
@@ -0,0 +1,18 @@
1
+ module RubyJmeter
2
+ module Plugins
3
+ class JsonPathAssertion
4
+ attr_accessor :doc
5
+ include Helper
6
+ def initialize(params={})
7
+ @doc = Nokogiri::XML(<<-EOF.strip_heredoc)
8
+ <com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.JSONPathAssertion guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.gui.JSONPathAssertionGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.JSONPathAssertion" testname="jp@gc - JSON Path Assertion" enabled="true">
9
+ <stringProp name="EXPECTED_VALUE"></stringProp>
10
+ <stringProp name="JSON_PATH"></stringProp>
11
+ <boolProp name="JSONVALIDATION">true</boolProp>
12
+ </com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.JSONPathAssertion>
13
+ EOF
14
+ update params
15
+ end
16
+ end
17
+ end
18
+ end
@@ -3,26 +3,10 @@ module RubyJmeter
3
3
  class PerfmonCollector
4
4
  attr_accessor :doc
5
5
  include Helper
6
- def initialize(name, params={}, filename="perfMon.jtl")
7
- metricNodes = params.collect do |m|
8
- "
9
- <collectionProp name=\"\">
10
- <stringProp name=\"\">#{m[:server]}</stringProp>
11
- <stringProp name=\"\">#{m[:port]}</stringProp>
12
- <stringProp name=\"\">#{m[:metric]}</stringProp>
13
- <stringProp name=\"\">#{m[:parameters]}</stringProp>
14
- </collectionProp>
15
- "
16
- end
17
-
18
- metricConnections = Nokogiri::XML(<<-XML.strip_heredoc)
19
- <collectionProp name="metricConnections">
20
- #{metricNodes.join "\n"}
21
- </collectionProp>
22
- XML
23
6
 
7
+ def initialize(params = {})
24
8
  @doc = Nokogiri::XML(<<-XML.strip_heredoc)
25
- <kg.apc.jmeter.perfmon.PerfMonCollector guiclass="kg.apc.jmeter.vizualizers.PerfMonGui" testclass="kg.apc.jmeter.perfmon.PerfMonCollector" testname="#{name}" enabled="true">
9
+ <kg.apc.jmeter.perfmon.PerfMonCollector guiclass="kg.apc.jmeter.vizualizers.PerfMonGui" testclass="kg.apc.jmeter.perfmon.PerfMonCollector" testname="#{params[:name] || 'PerfmonCollector'}" enabled="true">
26
10
  <boolProp name="ResultCollector.error_logging">false</boolProp>
27
11
  <objProp>
28
12
  <name>saveConfig</name>
@@ -41,7 +25,7 @@ module RubyJmeter
41
25
  <subresults>false</subresults>
42
26
  <responseData>false</responseData>
43
27
  <samplerData>false</samplerData>
44
- <xml>true</xml>
28
+ <xml>#{(params[:xml] || false).to_s}</xml>
45
29
  <fieldNames>false</fieldNames>
46
30
  <responseHeaders>false</responseHeaders>
47
31
  <requestHeaders>false</requestHeaders>
@@ -53,7 +37,7 @@ module RubyJmeter
53
37
  <sampleCount>true</sampleCount>
54
38
  </value>
55
39
  </objProp>
56
- <stringProp name="filename">#{filename}</stringProp>
40
+ <stringProp name="filename">#{params[:filename] || 'perfmon.jtl'}</stringProp>
57
41
  <longProp name="interval_grouping">1000</longProp>
58
42
  <boolProp name="graph_aggregated">false</boolProp>
59
43
  <stringProp name="include_sample_labels"></stringProp>
@@ -62,11 +46,34 @@ module RubyJmeter
62
46
  <stringProp name="end_offset"></stringProp>
63
47
  <boolProp name="include_checkbox_state">false</boolProp>
64
48
  <boolProp name="exclude_checkbox_state">false</boolProp>
65
- #{metricConnections.root.to_s}
49
+ #{metric_connections(params).root.to_s}
66
50
  </kg.apc.jmeter.perfmon.PerfMonCollector>
67
51
  XML
68
52
  update params
69
53
  end
54
+
55
+ private
56
+
57
+ def metric_connections(params)
58
+ Nokogiri::XML(<<-XML.strip_heredoc)
59
+ <collectionProp name="metricConnections">
60
+ #{metric_nodes(params[:nodes]).join "\n"}
61
+ </collectionProp>
62
+ XML
63
+ end
64
+
65
+ def metric_nodes(nodes)
66
+ nodes.collect do |node|
67
+ %(
68
+ <collectionProp name="">
69
+ <stringProp name="">#{node[:server]}</stringProp>
70
+ <stringProp name="">#{node[:port]}</stringProp>
71
+ <stringProp name="">#{node[:metric]}</stringProp>
72
+ <stringProp name="">#{node[:parameters]}</stringProp>
73
+ </collectionProp>
74
+ )
75
+ end
76
+ end
70
77
  end
71
78
  end
72
79
  end
@@ -1,3 +1,3 @@
1
1
  module RubyJmeter
2
- VERSION = '2.13.7'
2
+ VERSION = '2.13.8'
3
3
  end
data/spec/dsl_spec.rb CHANGED
@@ -225,7 +225,6 @@ describe 'DSL' do
225
225
 
226
226
  let(:fragment) { doc.search("//kg.apc.jmeter.threads.SteppingThreadGroup").first }
227
227
  it 'should match on on_sample_error' do
228
- puts fragment
229
228
  fragment.search(".//stringProp[@name='ThreadGroup.on_sample_error']").text.should == 'startnextloop'
230
229
  end
231
230
 
@@ -794,6 +793,30 @@ describe 'DSL' do
794
793
  end
795
794
  end
796
795
 
796
+ describe 'json assertion' do
797
+ let(:doc) do
798
+ test do
799
+ visit '/' do
800
+ assert json: '.key', value: 'value'
801
+ end
802
+ end.to_doc
803
+ end
804
+
805
+ let(:fragment) { doc.search('//com.atlantbh.jmeter.plugins.jsonutils.jsonpathassertion.JSONPathAssertion').first }
806
+
807
+ it 'should match on expected value' do
808
+ fragment.search(".//stringProp[@name='EXPECTED_VALUE']").text.should == "value"
809
+ end
810
+
811
+ it 'should match on json path' do
812
+ fragment.search(".//stringProp[@name='JSON_PATH']").text.should == ".key"
813
+ end
814
+
815
+ it 'should have json validation by default' do
816
+ fragment.search(".//boolProp[@name='JSONVALIDATION']").text.should == "true"
817
+ end
818
+ end
819
+
797
820
  describe 'scope main' do
798
821
  let(:doc) do
799
822
  test do
@@ -1045,6 +1068,37 @@ describe 'DSL' do
1045
1068
  it 'should match on response data' do
1046
1069
  fragment.search("//stringProp[@name='RESPONSE_DATA']").text.should == 'Some response data'
1047
1070
  end
1048
-
1049
1071
  end
1072
+
1073
+ describe 'perfmon collector' do
1074
+ let(:doc) do
1075
+ test do
1076
+ threads do
1077
+ perfmon_collector name: 'perfmon collector name',
1078
+ nodes:
1079
+ [
1080
+ {server: '1.1.1.1', port: 4444, metric: 'CPU', parameters: ''},
1081
+ {server: '2.2.2.2', port: 4444, metric: 'CPU', parameters: ''}
1082
+ ],
1083
+ filename: 'perf.jtl',
1084
+ xml: false
1085
+ end
1086
+ end.to_doc
1087
+ end
1088
+
1089
+ let(:fragment) { doc.search("//kg.apc.jmeter.perfmon.PerfMonCollector").first }
1090
+ let(:metric_connections) { fragment.search("//collectionProp[@name='metricConnections']").first }
1091
+
1092
+ it 'should match on name' do
1093
+ fragment.attributes['testname'].value.should == 'perfmon collector name'
1094
+ end
1095
+
1096
+ it 'should match on xml flag' do
1097
+ fragment.search(".//xml").first.text.should == 'false'
1098
+ end
1099
+
1100
+ it 'should match on first server ip' do
1101
+ metric_connections.search("//stringProp[@name='']").first.text.should == '1.1.1.1'
1102
+ end
1103
+ end
1050
1104
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-jmeter
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.13.7
4
+ version: 2.13.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Koopmans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-11 00:00:00.000000000 Z
11
+ date: 2015-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -79,6 +79,7 @@ files:
79
79
  - examples/basic_header.rb
80
80
  - examples/basic_http_request_defaults.rb
81
81
  - examples/basic_http_request_with_files.rb
82
+ - examples/basic_json_path_assertion.rb
82
83
  - examples/basic_json_path_extractor.rb
83
84
  - examples/basic_ldap_ext.rb
84
85
  - examples/basic_loadosophia.rb
@@ -242,6 +243,7 @@ files:
242
243
  - lib/ruby-jmeter/plugins/composite_graph.rb
243
244
  - lib/ruby-jmeter/plugins/console_status_logger.rb
244
245
  - lib/ruby-jmeter/plugins/dummy_sampler.rb
246
+ - lib/ruby-jmeter/plugins/json_path_assertion.rb
245
247
  - lib/ruby-jmeter/plugins/json_path_extractor.rb
246
248
  - lib/ruby-jmeter/plugins/latencies_over_time.rb
247
249
  - lib/ruby-jmeter/plugins/loadosophia_uploader.rb