{"id":13650819,"url":"https://github.com/flood-io/ruby-jmeter","last_synced_at":"2025-05-15T04:06:54.329Z","repository":{"id":9668525,"uuid":"11609648","full_name":"flood-io/ruby-jmeter","owner":"flood-io","description":"A Ruby based DSL for building JMeter test plans","archived":false,"fork":false,"pushed_at":"2023-10-27T01:48:04.000Z","size":513,"stargazers_count":750,"open_issues_count":38,"forks_count":140,"subscribers_count":47,"default_branch":"master","last_synced_at":"2024-05-02T07:11:34.366Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/flood-io.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2013-07-23T14:00:42.000Z","updated_at":"2024-04-24T15:31:25.000Z","dependencies_parsed_at":"2022-09-01T03:50:58.753Z","dependency_job_id":"6da0e203-de1b-480f-96ec-2ce914e2db5d","html_url":"https://github.com/flood-io/ruby-jmeter","commit_stats":null,"previous_names":[],"tags_count":80,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flood-io%2Fruby-jmeter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flood-io%2Fruby-jmeter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flood-io%2Fruby-jmeter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flood-io%2Fruby-jmeter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/flood-io","download_url":"https://codeload.github.com/flood-io/ruby-jmeter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247563933,"owners_count":20958971,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T02:00:41.338Z","updated_at":"2025-04-06T23:13:52.967Z","avatar_url":"https://github.com/flood-io.png","language":"Ruby","funding_links":[],"categories":["Automation","Ruby","Testing"],"sub_categories":["DSL"],"readme":"# Ruby-JMeter [![Build Status](https://travis-ci.org/flood-io/ruby-jmeter.png)](https://travis-ci.org/flood-io/ruby-jmeter) [![Code Climate](https://codeclimate.com/github/flood-io/ruby-jmeter.png)](https://codeclimate.com/github/flood-io/ruby-jmeter) [![Gem Version](https://badge.fury.io/rb/ruby-jmeter.svg)](http://badge.fury.io/rb/ruby-jmeter)\n\n\u003e **Ruby-JMeter** is built and maintained by [Flood IO](https://flood.io?utm_source=github), an easy to use load testing platform for any scale of testing.\n\nTired of using the JMeter GUI or looking at hairy XML files?\n\nThis gem lets you write test plans for JMeter in your favourite text editor, and optionally run them on [flood.io](http://flood.io).\n\n![](https://flood.io/images/logo-flood-medium.png)\n\n## Installation\n\nInstall it yourself as:\n\n    $ gem install ruby-jmeter\n\n## Basic Usage\n\n*RubyJmeter* exposes easy-to-use domain specific language for fluent communication with [JMeter](http://jmeter.apache.org/).It also includes API integration with [flood.io](https://flood.io), a cloud based load testing service.\n\nTo use the DSL, first let's require the gem:\n\n```ruby\nrequire 'ruby-jmeter'\n```\n\n### Basic Example\nLet's create a `test` and save the related `jmx` testplan to file, so we can edit/view it in JMeter.\n\n```ruby\ntest do\n  threads count: 10 do\n    visit name: 'Google Search', url: 'http://google.com'\n  end\nend.jmx\n```\n\nSo in this example, we just created a test plan, with 10 threads, each of which visited the search page at Google.\n\n### Generating a JMeter Test Plan (JMX)\nNote also how we called the `jmx` method of the test. Calling this method will write the contents of the JMeter test plan to file like this.\n\n```\n$ ruby testplan.rb\n[2013-04-23T10:29:03.275743 #42060]  INFO -- : Test plan saved to: jmeter.jmx\n```\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cjmeterTestPlan version=\"1.2\" properties=\"2.1\"\u003e\n  \u003chashTree\u003e\n    \u003cTestPlan guiclass=\"TestPlanGui\" testclass=\"TestPlan\" testname=\"Test Plan\" enabled=\"true\"\u003e\n      ...\n    \u003c/TestPlan\u003e\n  \u003c/hashTree\u003e\n\u003c/jmeterTestPlan\u003e\nJMX saved to: jmeter.jmx\n```\n\nThe file that is created can then be executed in the JMeter GUI. If you want to create the file with a different filename and/or path, just add the `file` parameter to the `jmx` method call like this.\n\n```ruby\ntest do\n  threads count: 10 do\n    visit name: 'Google Search', url: 'http://google.com'\n  end\nend.jmx(file: \"/tmp/my_testplan.jmx\")\n```\n\nWindows users should specify a path like this.\n\n```ruby\n.jmx(file: \"C:\\\\TEMP\\\\MyTestplan.jmx\")\n```\n\n### Running a JMeter Test Plan locally\nYou can execute the JMeter test plan by calling the `run` method of the test like this.\n\n```ruby\ntest do\n  threads count: 10 do\n    visit name: 'Google Search', url: 'http://google.com'\n  end\nend.run\n```\n\nThis will launch JMeter in headless (non-GUI mode) and execute the test plan. This is useful for shaking out the script before you push it to the Grid. There are a few parameters that you can set such as the `path` to the JMeter binary, the `file` path/name for the JMX file, the `log` path/name to output JMeter logs, the `jtl` path/name for JMeter results like this, and the `properties` path/name for the additional JMeter property file.\n\n```ruby\ntest do\n  threads count: 10 do\n    visit name: 'Google Search', url: 'http://google.com'\n  end\nend.run(\n  path: '/usr/share/jmeter/bin/',\n  file: 'jmeter.jmx',\n  log: 'jmeter.log',\n  jtl: 'results.jtl',\n  properties: 'jmeter.properties')\n```\n\n### Running a JMeter Test Plan on Flood IO\n\nYou can also execute JMeter test plans on Flood IO using our API. To do so, you require an account and API token. If you don't know your token, sign in to [flood.io](https://flood.io/) and check your account settings.\n\nTo execute the test on Flood IO, call the `flood` method on the test and pass it the API token like this.\n\n```ruby\ntest do\n  threads count: 10 do\n    visit name: 'Google Search', url: 'http://google.com'\n  end\nend.flood(\n  ENV['FLOOD_API_TOKEN'],\n  name: 'Demo',\n  privacy: 'public',\n  ## Select a grid or region to distribute this flood to\n  # grid: 'pmmi24XaSMnKjGVEtutroQ',\n  # region: 'ap-southeast-2'\n)\n```\n\nThis will then provide you with a link to the live test results on Flood IO like this.\n\n```\nI, [2015-02-24T11:15:25.669029 #14010]  INFO -- : Flood results at: https://flood.io/AbRWkFl7VODYCkQuy3ffvA\n```\n\nNote you will need to provide a `grid` or `region` parameter to the `.flood` method to describe which grid to distribute the flood test to. Otherwise it will default to the shared grid. You can find the Grid ID from the URL of the target grid in your [grids](https://flood.io/dashboard/grids) dashboard e.g.:\n\n![](https://s3.amazonaws.com/flood-io-support/Flood_IO_2015-02-24_11-43-21.jpg)\n\nFlood IO provides a shared grid for free, suitable for 5 minute tests, check your dashboard for the latest grid:\n\n![](https://s3.amazonaws.com/flood-io-support/Flood_IO_2015-02-24_11-44-29.jpg)\n\nAlternatively upgrade to a paid subscription on Flood IO and start your own grids on demand.\n\n## Advanced Usage\n\n### Blocks\n\nEach of the methods take an optional block delimited by `do` and `end` or braces `{}`\n\nBlocks let you nest methods within methods, so you can scope the execution of methods as you would in a normal JMeter test plan. For example.\n\n```ruby\ntest do\n  threads count: 100 do\n    visit name: 'Home', url: 'http://altentee.com' do\n      extract regex: \"content='(.+?)' name='csrf-token'\", name: 'csrf-token'\n    end\n  end\nend\n```\n\nThis would create a new test plan, with a 100 user thread group, each user visiting the \"Home\" page and extracting the CSRF token from the response of each visit.\n\nAll methods are nestable, but you should only have one test method, and typically only one threads method. For example, it wouldn't make sense to have a test plan within a test plan, or a thread group within a thread group. You can have multiple thread groups per test plan though. This implies *some* knowlege of how JMeter works.\n\nAll methods take a parameter hash to configure related options.\n\n### Threads\n\nYou can use the `threads` method to define a group of users:\n\n```ruby\nthreads count: 100\nthreads count: 100, continue_forever: true\nthreads count: 100, loops: 10\nthreads count: 100, rampup: 30, duration: 60\nthreads count: 100, scheduler: true,\n  start_time: Time.now.to_i * 1000,\n  end_time:   (Time.now.to_i * 1000) + (3600 * 1000)\n```\n\n### Cookies\n\nYou can use the `cookies` method to define a Cookie Manager:\n\n```ruby\ntest do\n  cookies\nend\n```\n\nThis methods takes an optional parameters hash. This is based on the [HTTP Cookie Manager](http://jmeter.apache.org/usermanual/component_reference.html#HTTP_Cookie_Manager).\n\n```ruby\ntest do\n  cookies clear_each_iteration: false\nend\n\ntest do\n  cookies policy: 'rfc2109', clear_each_iteration: true\nend\n```\n\n#### User-Defined Cookies\n\nThe `cookies` method parameters hash supports `user_defined_cookies`:\n\n```ruby\ntest do\n  cookie1 = { value: 'foo', name: 'bar', domain: 'google.co.uk', path: '/' }\n  cookie2 = { value: 'hello', name: 'world', domain: 'google.co.uk', secure: true }\n\n  cookies user_defined_cookies: [ cookie1, cookie2 ]\nend\n```\n\n`name` and `value` are required. `domain` and `path` are optional and default to blank.\n`secure` is optional and defaults to `false`.\n\n### Cache\n\nYou can use the `cache` method to define a Cache Manager:\n\n```ruby\ntest do\n  cache\nend\n```\n\nThis methods takes an optional parameters hash. This is based on the [HTTP Cache Manager](http://jmeter.apache.org/usermanual/component_reference.html#HTTP_Cache_Manager).\n\n```ruby\ntest do\n  cache clear_each_iteration: false\nend\n\ntest do\n  cache use_expires: true, clear_each_iteration: true\nend\n```\n\n### Authorization\n\nYou can use the `auth` method to define an Authorization Manager:\n\n```ruby\ntest do\n  auth\nend\n```\n\nThis methods takes an optional parameters hash. This is based on the [HTTP Authorization Manager](http://jmeter.apache.org/usermanual/component_reference.html#HTTP_Authorization_Manager).\n\n```ruby\ntest do\n  auth url: '/', username: 'tim', password: 'secret', domain: 'altentee.com'\nend\n```\n\n### Navigating\n\nYou can use the `visit` method to navigate to pages:\n\n```ruby\nvisit name: 'Google Search', url: 'http://google.com'\nvisit name: 'Google Search', url: 'http://google.com'\nvisit name: 'Google Search', url: 'http://google.com',\n  method: 'POST',\n  'DO_MULTIPART_POST': 'true'\nvisit name: 'Google Search', url: 'http://google.com',\n  use_keepalive: 'false'\nvisit name: 'Google Search', url: 'http://google.com',\n  connect_timeout: '1000',\n  response_timeout: '60000'\nvisit name: 'View Login', url: '/login',\n  protocol: \"https\",\n  port: 443\n```\n\n### Submitting a Form\n\nYou can use the `submit` method to POST a HTTP form:\n\n```ruby\nsubmit name: 'Submit Form', url: 'http://altentee.com/',\n  fill_in: {\n    username: 'tim',\n    password: 'password',\n    'csrf-token' =\u003e '${csrf-token}'\n  }\n```\n\nThis method makes a single request. The fill_in parameter lets you specify key/value pairs for form field parameters. You can also use the built in JMeter `${expression}` language to access run time variables extracted from previous responses.\n\n### POST JSON\n\n```ruby\n  header [\n    { name: 'Content-Type', value: 'application/json' }\n  ]\n\n  person = { name: \"Tom\" }\n\n  post name: 'Create Person',\n        url: \"https://example.com/people.json\",\n        raw_body: person.to_json do\n        with_xhr\n      end\n```\n\n### Think Time\n\nYou can use the `think_time` method to insert pauses into the simulation. This method is aliased as `random_timer`.\n\n```ruby\nthink_time 3000\n```\n\nThis method takes 2 parameters: the constant delay, and an optional variable delay. Both are specified in milliseconds. This is based on the [Gaussian Random Timer](http://jmeter.apache.org/usermanual/component_reference.html#Gaussian_Random_Timer). This timer pauses each thread request for a random amount of time, with most of the time intervals ocurring near a particular value. The total delay is the sum of the Gaussian distributed value (with mean 0.0 and standard deviation 1.0) times the deviation value you specify, and the offset value.\n\n```ruby\n# constant delay of 3 seconds\nthink_time 3000\n# constant delay of 1 seconds with variance up to 6 seconds.\nrandom_timer 1000, 6000\n```\n\n### Response Extractor\n\nYou can use the `extract` method to extract values from a server response using a regular expression. This is aliased as the `web_reg_save_param` method. This method is typically used inside a `visit` or `submit` block.\n\n```ruby\nextract regex: \"content='(.+?)' name='csrf-token'\", name: 'csrf-token'\n\nvisit name: 'Google', url: \"http://google.com/\" do\n  extract regex: 'aria-label=\"(.+?)\"', name: 'button_text'\n  extract xpath: '//button', name: 'button'\nend\n```\n\nThis is based on the [Regular Expression Extractor](http://jmeter.apache.org/usermanual/component_reference.html#Regular_Expression_Extractor) and [XPath Extractor](http://jmeter.apache.org/usermanual/component_reference.html#XPath_Extractor)\n\n```ruby\nvisit name: \"Altentee\", url: \"http://altentee.com\" do\n  extract regex: \"content='(.+?)' name='csrf-token'\", name: 'csrf-token'\n  extract regex: 'value=\"(.+?)\" name=\"JESSIONSID\"', name: 'JSESSIONID'\n  web_reg_save_param regex: 'value=\"(.+?)\" name=\"VIEWSTATE\"', name: 'VIEWSTATE'\n  extract name: 'username', regex: 'value=\"(.+?)\", name=\"username\"',\n    default: 'Tim Koopmans',\n    match_number: 1\n  extract name: 'shopping_item', regex: 'id=\"(.+?)\" name=\"book\"',\n    match_number: 0 # random\nend\n```\nYou can later use the extracted values with subsequent requests:\n\n```ruby\npost name: 'Authenticate', url: 'http://example.com/api/authentication/facebook', raw_body: '{\"auth_token\": \"FB_TOKEN\"}' do\n  extract name: 'auth_token', regex: %q{.*\"token\":\"([^\"]+)\".*}\n  extract name: 'user_id', regex: %q{.*\"user_id\":([^,]+),.*}\nend\n\nheader({name: 'X-Auth-Token', value: '${auth_token}'})\nvisit name: 'User profile', url: 'http://example.com/api/users/${user_id}'\n```\n\n### Response Assertion\n\nYou can use the `assert` method to extract values from a server response using a regular expression. This is aliased as the `web_reg_find` method. This method is typically used inside a `visit` or `submit` block.\n\n```ruby\nvisit \"Altentee\", \"http://altentee.com\" do\n  assert contains: \"We test, tune and secure your site\"\nend\n```\n\n\nThis method takes 3 parameters: the matching rule, the test string, and an optional parameters hash. This is based on the [Response Assertion](http://jmeter.apache.org/usermanual/component_reference.html#Response_Assertion).\n\n```ruby\nvisit \"Altentee\", \"http://altentee.com\" do\n  assert \"contains\": \"We test, tune and secure your site\"\n  assert \"not-contains\": \"We price gouge on cloud services\"\n  assert \"matches\": \"genius\"\n  assert \"not-matches\": \"fakers\"\n  assert \"contains\": \"magic\"\n  assert \"not-contains\": \"unicorns\", scope: 'all'\nend\n```\n\n## Roadmap\n\nThis work is being sponsored by Flood IO. Get in touch with us if you'd like to be involved.\n\n## Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Create some specs, make them pass\n4. Commit your changes (`git commit -am 'Add some feature'`)\n5. Push to the branch (`git push origin my-new-feature`)\n6. Create new Pull Request\n\n### IDL\n\nWe 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.\n\nTo 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`\n\nFor example:\n\n```sh\nflood/ruby-jmeter - [master●] » ruby lib/ruby-jmeter/idl.rb\nflood/ruby-jmeter - [master●] » git status\nOn branch master\nYour branch is up-to-date with 'origin/master'.\nChanges not staged for commit:\n  (use \"git add \u003cfile\u003e...\" to update what will be committed)\n  (use \"git checkout -- \u003cfile\u003e...\" to discard changes in working directory)\n\n  modified:   lib/ruby-jmeter/DSL.md\n  modified:   lib/ruby-jmeter/dsl/foreach_controller.rb\n  modified:   lib/ruby-jmeter/dsl/http_request.rb\n  modified:   lib/ruby-jmeter/dsl/http_request_defaults.rb\n  modified:   lib/ruby-jmeter/dsl/regular_expression_extractor.rb\n  modified:   lib/ruby-jmeter/dsl/response_assertion.rb\n  modified:   lib/ruby-jmeter/dsl/test_fragment.rb\n  modified:   lib/ruby-jmeter/dsl/user_parameters.rb\n```\n\nYou **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.\n\n### DSL\n\nMuch of the behaviour of the gem is defined in `lib/ruby-jmeter/dsl.rb` which is where you should be updating code. You can extend individual DSL component behaviour in `live/ruby-jmeter/extend/**/*.rb`\n\n### Plugins\n\nSome 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.\n\n### Bundler\n\nWe recommend using the Ruby gem bundle to manage your dependencies. Typical setup would be:\n\n\n```sh\ngem install bundler\ncd \u003cyour local clone\u003e\nbundle install\n```\n\nThen you can run any rake / test tasks with the prefix `bundle exec`\n\n### Tests\n\nIf contributing please add an appropriate test. See `spec/*_spec.rb` for examples. Tests can be run from the command line as follows:\n\n    $ bundle exec rspec\n\n### Examples\n\nIt 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:\n\n```ruby\n$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))\n```\n\n    $ flood/ruby-jmeter - [master●] » ruby examples/basic_assertion.rb\n      W, [2015-10-17T19:31:12.021004 #33216]  WARN -- : Test executing locally ...\n\nNote: most of the examples assume the JMeter binary is installed in `/usr/share/jmeter/bin/` however you can modify this in your example to something that suits your installation e.g.:\n\n\n```ruby\n...\nend.run(path: 'C/Program Files/JMeter/bin/', gui: true)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflood-io%2Fruby-jmeter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflood-io%2Fruby-jmeter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflood-io%2Fruby-jmeter/lists"}