Now go ahead and try hitting it using the browser.\nTip: remove timeout values and check what happens.\nI told you it was simple.\nNow, let's say you want to mix different protocols to test a bit more complex flow.\nHow about publishing an amqp message and making sure that, once a service consumes that message an endpoint of your is hit?\nIn order to achieve that, we have to make use of a plugin, given that amqp support is provided by a plugin.\nIn this scenario, we're talking about the amqp plugin.\nOnce we get this plugin installed we are able to create and run files like this:
Now go nuts!\nIt's all yours. Have fun.\nIf you want more examples about http, consider looking at this test.\nCheck this out, you'll find countless examples.\nCertainly one is what you need.
\n
if you need more
\n
$ nqr -h\nUsage: nqr [options] <test-file> [other-test-files...]\n\nTake a look at the full documentation: https://enqueuer.com\n\nOptions:\n -v, --version output the version number\n -b, --verbosity <level> set verbosity (default: \"warn\")\n -c, --config-file <path> set configurationFile\n -e, --parsers-list [parser] list available object parsers\n -f, --formatters-description [formatter] describe report formatters\n -o, --stdout-requisition-output add stdout as requisition output\n -m, --max-report-level-print <level> set max report level print\n -p, --protocols-description [protocol] describe protocols\n -t, --tests-list [expectedField] list available tests assertions\n -u, --loaded-modules-list list loaded modules\n -i, --show-passing-tests show passing tests\n -s, --store [store] add variables values to this session (default: [])\n -l, --add-plugin [plugin] add plugin (default: [])\n -a, --add-file <file> add file to be tested (default: [])\n -A, --add-file-and-ignore-others <file> add file to be tested and ignore others (default: [])\n -h, --help output usage information\n\nExamples:\n $ nqr --config-file config-file.yml --verbosity error --store key=value\n $ enqueuer -c config-file.yml test-file.yml --add-file another-test-file.yml -b info\n $ enqueuer test-file.yml --store someKey=true --store someOtherKey=false\n $ nqr --protocols-description -s key=value\n $ nqr -t expect\n $ nqr -l my-enqueuer-plugin-name -p plugin-protocol\n $ nqr -p http\n $ nqr --formatters-description json\n
\n\n
Components
\n
In order to accomplish more than just hitting enqueuer's repo or doing a quick self http hit, there are a few things that you'll probably need to know.\nDon't worry, it's not too much and, as mentioned earlier, there is a lot of examples here, just in case.\nThere are only three important component concepts: requisitions, publishers and subscriptions.\nThey work along with each other and are responsible for the full behavior of enqueuer.
\n
requisition
\n
Test scenario description. It tells what, when, and how test your applications and services.\nPicture it as if it was a collection of publishers, subscriptions and other requisitions.\nIt helps because this is exactly what it is.\nAs the others components, it has some attributes. All of them are optionals. And it supports multi-level test scenarios out of the box. Yeap, go as recursive as you want.\nEvery test file is a requisition.\nYou don't know some of these attributes values yet? Don't worry, just put a variable there and let enqueuer replace it with the value you set later.\nVariable replacements are available through the entire requisition.
\n
requisition attributes
\n
These are the requisition attributes:
\n
name \nDescribes what the requisition is suppose to do.\nDefaults to requisition index.
\n
name: requisition action\n
\n
timeout \nDefaults to 5000.\nSets in milliseconds how long the requisition waits to expire.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
delay \nDefaults to 0. Sets in milliseconds how long the test waits before starting. Check this to get the full idea.
\n
delay: 0\n
\n
iterations \nDefaults to 1. Sets how many times this test will be executed. Check this and this to get the full idea.
\n
iterations: 3\n
\n
ignore \nDefaults to false. Tells to enqueuer that this requisitions should be skipped. Check this to see it working.
\n
ignore: true\n
\n
parallel \nDefaults to false. Immediate children requisitions should be executed in parallel mode.\nTake a look at this to see it working.
\n
parallel: true\n
\n
import \nAllows requisition to be dynamically defined, be it by loading an external file or creating dynamically by other requisitions. Want to reuse the same requisition multiple times? This is you you need.\nTake a look at this to behold this feature.
\n
import: path/to/another/requisition/file\n
\n
publishers \nList of publishers. They're executed simultaneously, therefore, the order is irrelevant.
\n
publishers:\n- name: some publisher name\n type: http\n- type: tcp\n
\n
subscriptions \nList of subscriptions. They're executed simultaneously, therefore, the order is irrelevant.
\n
subscriptions:\n- name: some subscription name\n type: udp\n- name: another subscription name\n type: file\n
\n
requisitions \nA list of child scenarios. List of requisitions.\nBy default, they're executed sequentially, therefore, the order is relevant.\nUnless the parallel attribute is set to true, what makes them get executed simultaneously,\nCheck this example, it may help.
\n
requisitions:\n- name: some requisition name\n iterations: 2\n- name: another requisition name\n delay: 200\n
\n
events
\n
Available events are described here. A this object is available to access and change requisition attributes.
A publisher action is triggered by enqueuer itself. It acts whereas a subscriptionreacts.\nIt publishes something, it writes, it enqueues, hits and endpoint... These kinds of actions.\nIt's worth noting that it always creates a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if the message got published.
\n
publisher attributes
\n
Every publisher has its own properties, depending on its protocol and implementation.\nThe built-in http publisher implementation, for instance, demands a url, a method, and a payload, if the method is not a GET.\nOn the other hand, the built-in tcp publisher implementation requires a serverAddress and a port.\nThese are the publisher attributes:
\n
name \nDefaults to publisher index.\nDescribes what the publisher is supposed to do.
\n
name: publisher action\n
\n
type \nMandatory. Key tag to identify which publisher will be instantiated
\n
type: http\n
\n
payload \nSince a publisher usually publishes something, it's very likely you have to set a value here.\nThe message itself that will be send through this protocol. Be it a string, a number, a boolean value or even whole objects.
\n
payload: value\n
\n
ignore \nDefaults to false. Tells to enqueuer that this publisher should be skipped. Check this to see it working.
\n
ignore: true\n
\n
events
\n
Available events are described here. A this object is available to access and change publisher attributes.\nDepending on the protocol and its implementation, such as http and tcp, there may exist special events, such as onMessageReceived event and a special object given message.\nOn the other hand, an asynchronous protocol, like: udp and amqp, usually do not provide it.
A subscription is an \"under demand\" event. It reacts whereas a publisheracts.\nIt consumes something, it reads, it dequeues, gets hit... These kinds of actions.\nThis means that it is not triggered by enqueuer itself.\nRather than that, enqueuer waits on an external event to be triggered and then it asserts against the message that was passed to the subscription.\nIt's worth noting that it always receives a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if a message got received.
\n
subscription attributes
\n
Every subscription has its own properties, depending on its protocol and implementation.\nThe built-in http subscription implementation, for instance, demands an endpoint, a method, and a port, if the method is not a GET.\nOn the other hand, the built-in tcp subscription implementation requires only a port.
\n
These are the subscription attributes:
\n
name \nDefaults to subscription index.\nDescribes what the subscription is supposed to do.
\n
name: subscription action\n
\n
type \nMandatory. Key tag to identify which subscription will be instantiated
\n
type: http\n
\n
avoid \nIdentifies whether or not this subscription should not receive any message. Defaults to false.\nIf set and a message is received a failing test will be generated.\nTake a look at this to see it working.\nOn the other hand, when it's false and no message is received in a given timeout. The subscription is valid.
\n
avoid: false\n
\n
timeout \nSets in milliseconds how long the subscription waits to expire. Defaults to 3000.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
ignore \nDefaults to false. Tells to enqueuer that this subscription should be skipped. Check this to see it working.
\n
ignore: true \n
\n
events
\n
Available events are described here. A this object is available to access and change subscription attributes.
Events are hook methods executed by enqueuer when an action occurs on publishers, subscriptions or requisitions.\nThis is where you'll write your tests. In its assertions field.\nThere will be a variable called this and, depending on the event's owner, it has an alias publisher, subscription or requisition.\nYou're free to explore them however you want, even doing things like this:
By default, there are three hook events available:
\n
onInit \nAvailable in requisitions, publishers and subscriptions. It gets executed as soon as the component is initialized.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
onFinish \nAvailable in requisitions, publishers and subscriptions. It gets executed when the component is about to finish.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
custom\nDepending on the protocol implementation/library/author's mood, the publisher/subscription may have additional hooks.\nSuch as onError, onResponseReceived, onFileNotFound and onRedirect...\nHttp-proxy subscription test file is an excellent example, check it out.
\n
fields
\n
Every hook object has 3 properties:
\n
script \nJavascript code snippet executed when the event is triggered.\nYeah, I mean it. See it it by yourself.\nBut be careful, with great power comes great responsibility.
\n
store \nData to be persisted across requisitions.
\n
assertions \nArray of assertions.\nRun $ nqr -t to see available ones.\nConsider looking at this test example.\nOf course, just like almost everything else in enqueuer world, you can extend this available list using some plugin.\nYou can check them out or even write your own.
Now that you know what are requisitions, publishers, subscriptions and events. How about seeing how they interact with each other in a fancier way?
\n
\n\n
Configuration File
\n
To save yourself some time, a configuration file may be used.\nConfiguration files tell enqueuer which tests will be executed, log-level, and which output test report files should be generated.\nThis file tells how enqueuer should be executed.\nTo run enqueuer with the configuration:
files \nRequisition file names or glob. Enqueuer runs every file that matches an element value.
\n
files:\n- 1.yml\n- 2.yml\n- *.json\n
\n
parallel \nDefaults to false. Requisition files should be executed in parallel mode. The requisition file itself is still sequential, but the files are executes in parallel.
\n
parallel: true\n
\n
log-level \nDefaults to warning. Defines how information are logged in the console. Accepted values are: trace; debug; info; warning (default); error; and fatal.
\n
log-level: trace\n
\n
max-report-level-print \nDefaults to 1. The deepest level of report to be printed to the console.
outputs \nOnce enqueuer runs every execution, it compiles a summary and sends it to every publisher listed in output.\nAn important thing to note is that every available report publisher is available here.\nYes, it means that you are able to send this report through http, tcp, etc. or through a plugin one or a custom one.\nYou can run $ nqr -p to check available report publishers installed.\nAnother important thing to note is the format value. By default a json summary is generated, but you can change it to whatever format you would like, such as: Xunit, html\nYou can run $ nqr -f to check available installed formats or even write your own
store \nValues defined here use the 'key: value' pattern and are available to every test scenario throughout the entire execution
\n
store:\n variableKey: \"my value\" # Defines 'variableKey' key and its value 'my value'. \n \n 'separated key': 6\n \n object: # You can even define whole objects here:\n first: first value\n second:\n nested: thing\n
\n
example
\n
Here's a complete example of a configuration file.
\n\n
Variables
\n
Providing power and flexibility, enqueuer allows you to use variables placeholder replacement.\nThat's why there is a store field and you'll see a lot of << and {{ being used in the examples files.\nIt works as simple as this:
\n
name: my name is <<variableKey>>\n
\n
Every time enqueuer sees these kind of notations, it searches in its store for a key/value pair like:
\n
variableKey: `enqueuer`\n
\n
Then, when enqueuer parses the original map, it gets translated to this:
\n
name: my name is enqueuer\n
\n
By default, every ENV_VAR set is loaded automatically to the store. Check this example.
\n
set a variable
\n
There are a few ways to set a value in the store.
\n
configuration file
\n
Configuration file store object. Set it as you wish, as you can see here
\n
command line
\n
A command line argument using the key=value format. This way:
\n
$ nqr --store key=value -s anotherVariable=true\n
\n
event
\n
Dynamically set it through any event.\nBe it in its script field or straight through its store field.\nBoth ways work:
The easiest one is to type <<variableKey>> or {{variableKey}} where you want it to be replaced in a test file, as you can see here
\n
js code snippet
\n
Using the store object. It's attributes are the keys and their values are their respective values.\nTherefore, you're free to use store.variableKey, console.log(store.variableKey); or console.log(2 * store['separated key']); and get them.\nLike this one.
It get's event better.\nDue its fantastic plugin architecture design, you can extend its default modules and use any of these plugins or event write your own to parse however you want.\nThe built-in modules for object parsers are: json, yml, csv and file.\nRun $ nqr -e to see available ones.
You're probably aware by now but it doesn't hurt do emphasize it: enqueuer provides an amazingly powerful plugin extensible architecture.\nIt has several plugins available, but if none of them pleases you, you're free to create your own.\nAlbeit you don't have to share the one you created, we encourage you to do so. Then go ahead and publish yours to npm and add it to our plugins list.
\n
plugin types
\n
So far, you're able to extend enqueuer default behavior in four ways. Using a protocol plugin, an object parser plugin, an asserter plugin and using a report formatter plugin.
\n
protocol
\n
A protocol plugin enables you to use a different publisher/subscription types.\nRun $ nqr -p [protocol-name] to get the full available list:
Each one listed above has a respective example in the examples folder.\nThis one, for instance, provides support for amqp protocol, so you can create this publisher and subscription:
An object parser plugin enables you to read and parse files as you wish.\nThis test example demonstrates how to use it,\nRun $ nqr -e [object-parser-name] to check available ones:
\n
parsers: \n- yml, yaml\n- json\n- file\n- csv\n
\n
This one, for example, provides the ability to read xml files and inject their values like this:
\n
xmlContent: <<xml://path/to/xml/file.xml>>\n
\n
asserter
\n
An asserter plugin provides you a nicely way to use different assertions than these built-in ones.
Run $ nqr -t to get the full available list.\nConsider looking at this test example.
\n
report formatter
\n
A report formatter plugin gives you the ability to export enqueuer reports the way you want.\nRun $ nqr -f [formatter-name] to list available report formatters:
Consider looking at the example of configuration file to see it in use.\nThis one, for instance, generates xUnit like reports from enqueuer's output.
\n
plugin installation
\n
In order to enqueuer get awareness that you want to use a plugin, you have to tell it, right?\nYou can tell enqueuer to use a plugin in three different ways: using it as a command line argument, through the configuration file or letting enqueuer finding it in a default location.
\n
command line
\n
Tell enqueuer to use your plugin through command line this way $ nqr -l <plugin-folder> -l <another-plugin-folder>.\nWhere plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
configuration file
\n
Tell enqueuer to use your plugin through configuration file this way:
Where plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
implicitly
\n
When enqueuer runs, it looks for modules in its same installation directory or in .nqr folder in the home directory, a.k.a. ~/ folder in linux distributions.\nTherefore, if you run:
You'll see that the enqueuer-plugin-amqp plugin will be loaded.\nEvery enqueuer compatible module gets implicitly loaded.\nIn order to be enqueuer compatible, a module has to have an entryPoint exported function in its main file and, in its package.json file, it has to have either 'enqueuer' or 'nqr' as keywords.
\n
Stacker
\n
Looking for a really really good looking an human error proof solution way of writing these requisition files? \nConsider taking a look at stacker: open source, cross-platform, multi protocol client testing tool.\nThe official enqueuer's best friend forever. Do amazing things and change the world with enqueuer’s GUI!\nWith them, you create, manage and run requisitions and and see their results in a really nice way.\nSee this amazing beauty with your own eyes to get an idea of how it works:
\n
\n\n
Open source
\n
We (by 'we' we mean enqueuer's maintainers not the human race, unfortunately) are very opened to any kind of contributions in general.\nAs long as they make sense and add value to the product, you're free to go.\nWe mean it, do it. Even if it's a typo fix in this README file. Go ahead.\nIf you like it but don't want to waste time creating a pull request, no problem either.\nCreate an issue, or, even easier, give it a github star. It's cheap and it doesn't hurt anyone.\nYou know what? Just head up to enqueuer's github repo and keep staring at its repo.\nIt may help somehow.
In order to contribute with some code, you have to follow a few steps.\nFirst of all, get the code:
\n
$ git clone git@github.com:enqueuer-land/enqueuer.git\n$ cd enqueuer\n
\n
Get its dependencies installed:
\n
$ npm install\n
\n
Build it:
\n
$ npm run build\n
\n
Go for it. Make the changes you want.\nAfter everything is done:
\n
$ npm run all\n
\n
Commit it:
\n
$ npm run commit\n
\n
Push it:
\n
$ git push\n
\n
feedback
\n
We'd love to get your feedback!\nIf you have any comments, suggestions, etc. you can reach us here.
\n
\n\n
\n
\n\n\n\n
\n
\n\n \n
\n \n\n
\n\n \n\n\n\n\n
\n \n \n You can’t perform that action at this time.\n
\n\n\n \n \n \n \n \n \n \n
\n \n You signed in with another tab or window. Reload to refresh your session.\n You signed out in another tab or window. Reload to refresh your session.\n
\n Over 40 million developers use GitHub together\n to host and review code, project manage, and build software together\n across more than 100 million projects.\n
Now go ahead and try hitting it using the browser.\nTip: remove timeout values and check what happens.\nI told you it was simple.\nNow, let's say you want to mix different protocols to test a bit more complex flow.\nHow about publishing an amqp message and making sure that, once a service consumes that message an endpoint of your is hit?\nIn order to achieve that, we have to make use of a plugin, given that amqp support is provided by a plugin.\nIn this scenario, we're talking about the amqp plugin.\nOnce we get this plugin installed we are able to create and run files like this:
Now go nuts!\nIt's all yours. Have fun.\nIf you want more examples about http, consider looking at this test.\nCheck this out, you'll find countless examples.\nCertainly one is what you need.
\n
if you need more
\n
$ nqr -h\nUsage: nqr [options] <test-file> [other-test-files...]\n\nTake a look at the full documentation: https://enqueuer.com\n\nOptions:\n -v, --version output the version number\n -b, --verbosity <level> set verbosity (default: \"warn\")\n -c, --config-file <path> set configurationFile\n -e, --parsers-list [parser] list available object parsers\n -f, --formatters-description [formatter] describe report formatters\n -o, --stdout-requisition-output add stdout as requisition output\n -m, --max-report-level-print <level> set max report level print\n -p, --protocols-description [protocol] describe protocols\n -t, --tests-list [expectedField] list available tests assertions\n -u, --loaded-modules-list list loaded modules\n -i, --show-passing-tests show passing tests\n -s, --store [store] add variables values to this session (default: [])\n -l, --add-plugin [plugin] add plugin (default: [])\n -a, --add-file <file> add file to be tested (default: [])\n -A, --add-file-and-ignore-others <file> add file to be tested and ignore others (default: [])\n -h, --help output usage information\n\nExamples:\n $ nqr --config-file config-file.yml --verbosity error --store key=value\n $ enqueuer -c config-file.yml test-file.yml --add-file another-test-file.yml -b info\n $ enqueuer test-file.yml --store someKey=true --store someOtherKey=false\n $ nqr --protocols-description -s key=value\n $ nqr -t expect\n $ nqr -l my-enqueuer-plugin-name -p plugin-protocol\n $ nqr -p http\n $ nqr --formatters-description json\n \nContributing:\n https://github.com/enqueuer-land/enqueuer\n
\n\n
Components
\n
In order to accomplish more than just hitting enqueuer's repo or doing a quick self http hit, there are a few things that you'll probably need to know.\nDon't worry, it's not too much and, as mentioned earlier, there is a lot of examples here, just in case.\nThere are only three important component concepts: requisitions, publishers and subscriptions.\nThey work along with each other and are responsible for the full behavior of enqueuer.
\n
requisition
\n
Test scenario description. It tells what, when, and how test your applications and services.\nPicture it as if it was a collection of publishers, subscriptions and other requisitions.\nIt helps because this is exactly what it is.\nAs the others components, it has some attributes. All of them are optionals. And it supports multi-level test scenarios out of the box. Yeap, go as recursive as you want.\nEvery test file is a requisition.\nYou don't know some of these attributes values yet? Don't worry, just put a variable there and let enqueuer replace it with the value you set later.\nVariable replacements are available through the entire requisition.
\n
requisition attributes
\n
These are the requisition attributes:
\n
name \nDescribes what the requisition is suppose to do.\nDefaults to requisition index.
\n
name: requisition action\n
\n
timeout \nDefaults to 5000.\nSets in milliseconds how long the requisition waits to expire.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
delay \nDefaults to 0. Sets in milliseconds how long the test waits before starting. Check this to get the full idea.
\n
delay: 0\n
\n
iterations \nDefaults to 1. Sets how many times this test will be executed. Check this and this to get the full idea.
\n
iterations: 3\n
\n
ignore \nDefaults to false. Tells to enqueuer that this requisitions should be skipped. Check this to see it working.
\n
ignore: true\n
\n
parallel \nDefaults to false. Immediate children requisitions should be executed in parallel mode.\nTake a look at this to see it working.
\n
parallel: true\n
\n
import \nAllows requisition to be dynamically defined, be it by loading an external file or creating dynamically by other requisitions. Want to reuse the same requisition multiple times? This is you you need.\nTake a look at this to behold this feature.
\n
import: path/to/another/requisition/file\n
\n
publishers \nList of publishers. They're executed simultaneously, therefore, the order is irrelevant.
\n
publishers:\n- name: some publisher name\n type: http\n- type: tcp\n
\n
subscriptions \nList of subscriptions. They're executed simultaneously, therefore, the order is irrelevant.
\n
subscriptions:\n- name: some subscription name\n type: udp\n- name: another subscription name\n type: file\n
\n
requisitions \nA list of child scenarios. List of requisitions.\nBy default, they're executed sequentially, therefore, the order is relevant.\nUnless the parallel attribute is set to true, what makes them get executed simultaneously,\nCheck this example, it may help.
\n
requisitions:\n- name: some requisition name\n iterations: 2\n- name: another requisition name\n delay: 200\n
\n
events
\n
Available events are described here. A this object is available to access and change requisition attributes.
A publisher action is triggered by enqueuer itself. It acts whereas a subscriptionreacts.\nIt publishes something, it writes, it enqueues, hits and endpoint... These kinds of actions.\nIt's worth noting that it always creates a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if the message got published.
\n
publisher attributes
\n
Every publisher has its own properties, depending on its protocol and implementation.\nThe built-in http publisher implementation, for instance, demands a url, a method, and a payload, if the method is not a GET.\nOn the other hand, the built-in tcp publisher implementation requires a serverAddress and a port.\nThese are the publisher attributes:
\n
name \nDefaults to publisher index.\nDescribes what the publisher is supposed to do.
\n
name: publisher action\n
\n
type \nMandatory. Key tag to identify which publisher will be instantiated
\n
type: http\n
\n
payload \nSince a publisher usually publishes something, it's very likely you have to set a value here.\nThe message itself that will be send through this protocol. Be it a string, a number, a boolean value or even whole objects.
\n
payload: value\n
\n
ignore \nDefaults to false. Tells to enqueuer that this publisher should be skipped. Check this to see it working.
\n
ignore: true\n
\n
events
\n
Available events are described here. A this object is available to access and change publisher attributes.\nDepending on the protocol and its implementation, such as http and tcp, there may exist special events, such as onMessageReceived event and a special object given message.\nOn the other hand, an asynchronous protocol, like: udp and amqp, usually do not provide it.
A subscription is an \"under demand\" event. It reacts whereas a publisheracts.\nIt consumes something, it reads, it dequeues, gets hit... These kinds of actions.\nThis means that it is not triggered by enqueuer itself.\nRather than that, enqueuer waits on an external event to be triggered and then it asserts against the message that was passed to the subscription.\nIt's worth noting that it always receives a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if a message got received.
\n
subscription attributes
\n
Every subscription has its own properties, depending on its protocol and implementation.\nThe built-in http subscription implementation, for instance, demands an endpoint, a method, and a port, if the method is not a GET.\nOn the other hand, the built-in tcp subscription implementation requires only a port.
\n
These are the subscription attributes:
\n
name \nDefaults to subscription index.\nDescribes what the subscription is supposed to do.
\n
name: subscription action\n
\n
type \nMandatory. Key tag to identify which subscription will be instantiated
\n
type: http\n
\n
avoid \nIdentifies whether or not this subscription should not receive any message. Defaults to false.\nIf set and a message is received a failing test will be generated.\nTake a look at this to see it working.\nOn the other hand, when it's false and no message is received in a given timeout. The subscription is valid.
\n
avoid: false\n
\n
timeout \nSets in milliseconds how long the subscription waits to expire. Defaults to 3000.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
ignore \nDefaults to false. Tells to enqueuer that this subscription should be skipped. Check this to see it working.
\n
ignore: true \n
\n
events
\n
Available events are described here. A this object is available to access and change subscription attributes.
Events are hook methods executed by enqueuer when an action occurs on publishers, subscriptions or requisitions.\nThis is where you'll write your tests. In its assertions field.\nThere will be a variable called this and, depending on the event's owner, it has an alias publisher, subscription or requisition.\nYou're free to explore them however you want, even doing things like this:
By default, there are three hook events available:
\n
onInit \nAvailable in requisitions, publishers and subscriptions. It gets executed as soon as the component is initialized.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
onFinish \nAvailable in requisitions, publishers and subscriptions. It gets executed when the component is about to finish.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
custom\nDepending on the protocol implementation/library/author's mood, the publisher/subscription may have additional hooks.\nSuch as onError, onResponseReceived, onFileNotFound and onRedirect...\nHttp-proxy subscription test file is an excellent example, check it out.
\n
fields
\n
Every hook object has 3 properties:
\n
script \nJavascript code snippet executed when the event is triggered.\nYeah, I mean it. See it it by yourself.\nBut be careful, with great power comes great responsibility.
\n
store \nData to be persisted across requisitions.
\n
assertions \nArray of assertions.\nRun $ nqr -t to see available ones.\nConsider looking at this test example.\nOf course, just like almost everything else in enqueuer world, you can extend this available list using some plugin.\nYou can check them out or even write your own.
Now that you know what are requisitions, publishers, subscriptions and events. How about seeing how they interact with each other in a fancier way?
\n
\n\n
Configuration File
\n
To save yourself some time, a configuration file may be used.\nConfiguration files tell enqueuer which tests will be executed, log-level, and which output test report files should be generated.\nThis file tells how enqueuer should be executed.\nTo run enqueuer with the configuration:
files \nRequisition file names or glob. Enqueuer runs every file that matches an element value.
\n
files:\n- 1.yml\n- 2.yml\n- *.json\n
\n
parallel \nDefaults to false. Requisition files should be executed in parallel mode. The requisition file itself is still sequential, but the files are executes in parallel.
\n
parallel: true\n
\n
log-level \nDefaults to warning. Defines how information are logged in the console. Accepted values are: trace; debug; info; warning (default); error; and fatal.
\n
log-level: trace\n
\n
max-report-level-print \nDefaults to 1. The deepest level of report to be printed to the console.
outputs \nOnce enqueuer runs every execution, it compiles a summary and sends it to every publisher listed in output.\nAn important thing to note is that every available report publisher is available here.\nYes, it means that you are able to send this report through http, tcp, etc. or through a plugin one or a custom one.\nYou can run $ nqr -p to check available report publishers installed.\nAnother important thing to note is the format value. By default a json summary is generated, but you can change it to whatever format you would like, such as: Xunit, html\nYou can run $ nqr -f to check available installed formats or even write your own
store \nValues defined here use the 'key: value' pattern and are available to every test scenario throughout the entire execution
\n
store:\n variableKey: \"my value\" # Defines 'variableKey' key and its value 'my value'. \n \n 'separated key': 6\n \n object: # You can even define whole objects here:\n first: first value\n second:\n nested: thing\n
\n
example
\n
Here's a complete example of a configuration file.
\n\n
Variables
\n
Providing power and flexibility, enqueuer allows you to use variables placeholder replacement.\nThat's why there is a store field and you'll see a lot of << and {{ being used in the examples files.\nIt works as simple as this:
\n
name: my name is <<variableKey>>\n
\n
Every time enqueuer sees these kind of notations, it searches in its store for a key/value pair like:
\n
variableKey: `enqueuer`\n
\n
Then, when enqueuer parses the original map, it gets translated to this:
\n
name: my name is enqueuer\n
\n
By default, every ENV_VAR set is loaded automatically to the store. Check this example.
\n
set a variable
\n
There are a few ways to set a value in the store.
\n
configuration file
\n
Configuration file store object. Set it as you wish, as you can see here
\n
command line
\n
A command line argument using the key=value format. This way:
\n
$ nqr --store key=value -s anotherVariable=true\n
\n
event
\n
Dynamically set it through any event.\nBe it in its script field or straight through its store field.\nBoth ways work:
The easiest one is to type <<variableKey>> or {{variableKey}} where you want it to be replaced in a test file, as you can see here
\n
js code snippet
\n
Using the store object. It's attributes are the keys and their values are their respective values.\nTherefore, you're free to use store.variableKey, console.log(store.variableKey); or console.log(2 * store['separated key']); and get them.\nLike this one.
It get's event better.\nDue its fantastic plugin architecture design, you can extend its default modules and use any of these plugins or event write your own to parse however you want.\nThe built-in modules for object parsers are: json, yml, csv and file.\nRun $ nqr -e to see available ones.
You're probably aware by now but it doesn't hurt do emphasize it: enqueuer provides an amazingly powerful plugin extensible architecture.\nIt has several plugins available, but if none of them pleases you, you're free to create your own.\nAlbeit you don't have to share the one you created, we encourage you to do so. Then go ahead and publish yours to npm and add it to our plugins list.
\n
plugin types
\n
So far, you're able to extend enqueuer default behavior in four ways. Using a protocol plugin, an object parser plugin, an asserter plugin and using a report formatter plugin.
\n
protocol
\n
A protocol plugin enables you to use a different publisher/subscription types.\nRun $ nqr -p [protocol-name] to get the full available list:
Each one listed above has a respective example in the examples folder.\nThis one, for instance, provides support for amqp protocol, so you can create this publisher and subscription:
An object parser plugin enables you to read and parse files as you wish.\nThis test example demonstrates how to use it,\nRun $ nqr -e [object-parser-name] to check available ones:
\n
parsers: \n- yml, yaml\n- json\n- file\n- csv\n
\n
This one, for example, provides the ability to read xml files and inject their values like this:
\n
xmlContent: <<xml://path/to/xml/file.xml>>\n
\n
asserter
\n
An asserter plugin provides you a nicely way to use different assertions than these built-in ones.
Run $ nqr -t to get the full available list.\nConsider looking at this test example.
\n
report formatter
\n
A report formatter plugin gives you the ability to export enqueuer reports the way you want.\nRun $ nqr -f [formatter-name] to list available report formatters:
Consider looking at the example of configuration file to see it in use.\nThis one, for instance, generates xUnit like reports from enqueuer's output.
\n
plugin installation
\n
In order to enqueuer get awareness that you want to use a plugin, you have to tell it, right?\nYou can tell enqueuer to use a plugin in three different ways: using it as a command line argument, through the configuration file or letting enqueuer finding it in a default location.
\n
command line
\n
Tell enqueuer to use your plugin through command line this way $ nqr -l <plugin-folder> -l <another-plugin-folder>.\nWhere plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
configuration file
\n
Tell enqueuer to use your plugin through configuration file this way:
Where plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
implicitly
\n
When enqueuer runs, it looks for modules in its same installation directory or in .nqr folder in the home directory, a.k.a. ~/ folder in linux distributions.\nTherefore, if you run:
You'll see that the enqueuer-plugin-amqp plugin will be loaded.\nEvery enqueuer compatible module gets implicitly loaded.\nIn order to be enqueuer compatible, a module has to have an entryPoint exported function in its main file and, in its package.json file, it has to have either 'enqueuer' or 'nqr' as keywords.
\n
Stacker
\n
Looking for a really really good looking an human error proof solution way of writing these requisition files? \nConsider taking a look at stacker: open source, cross-platform, multi protocol client testing tool.\nThe official enqueuer's best friend forever. Do amazing things and change the world with enqueuer’s GUI!\nWith them, you create, manage and run requisitions and and see their results in a really nice way.\nSee this amazing beauty with your own eyes to get an idea of how it works:
\n
\n\n
Open source
\n
We (by 'we' we mean enqueuer's maintainers not the human race, unfortunately) are very opened to any kind of contributions in general.\nAs long as they make sense and add value to the product, you're free to go.\nWe mean it, do it. Even if it's a typo fix in this README file. Go ahead.\nIf you like it but don't want to waste time creating a pull request, no problem either.\nCreate an issue, or, even easier, give it a github star. It's cheap and it doesn't hurt anyone.\nYou know what? Just head up to enqueuer's github repo and keep staring at its repo.\nIt may help somehow.
In order to contribute with some code, you have to follow a few steps.\nFirst of all, get the code:
\n
$ git clone git@github.com:enqueuer-land/enqueuer.git\n$ cd enqueuer\n
\n
Get its dependencies installed:
\n
$ npm install\n
\n
Build it:
\n
$ npm run build\n
\n
Go for it. Make the changes you want.\nAfter everything is done:
\n
$ npm run all\n
\n
Commit it:
\n
$ npm run commit\n
\n
Push it:
\n
$ git push\n
\n
feedback
\n
We'd love to get your feedback!\nIf you have any comments, suggestions, etc. you can reach us here.
\n
\n\n
\n
\n\n\n\n\n
\n
\n\n \n
\n \n\n
\n\n \n\n\n\n\n
\n \n \n You can’t perform that action at this time.\n
\n\n\n \n \n \n \n \n \n \n
\n \n You signed in with another tab or window. Reload to refresh your session.\n You signed out in another tab or window. Reload to refresh your session.\n
Now go ahead and try hitting it using the browser.\nTip: remove timeout values and check what happens.\nI told you it was simple.\nNow, let's say you want to mix different protocols to test a bit more complex flow.\nHow about publishing an amqp message and making sure that, once a service consumes that message an endpoint of your is hit?\nIn order to achieve that, we have to make use of a plugin, given that amqp support is provided by a plugin.\nIn this scenario, we're talking about the amqp plugin.\nOnce we get this plugin installed we are able to create and run files like this:
Now go nuts!\nIt's all yours. Have fun.\nIf you want more examples about http, consider looking at this test.\nCheck this out, you'll find countless examples.\nCertainly one is what you need.
\n
if you need more
\n
$ nqr -h\nUsage: nqr [options] <test-file> [other-test-files...]\n\nTake a look at the full documentation: https://enqueuer.com\n\nOptions:\n -v, --version output the version number\n -b, --verbosity <level> set verbosity (default: \"warn\")\n -c, --config-file <path> set configurationFile\n -e, --parsers-list [parser] list available object parsers\n -f, --formatters-description [formatter] describe report formatters\n -o, --stdout-requisition-output add stdout as requisition output\n -m, --max-report-level-print <level> set max report level print\n -p, --protocols-description [protocol] describe protocols\n -t, --tests-list [expectedField] list available tests assertions\n -u, --loaded-modules-list list loaded modules\n -i, --show-passing-tests show passing tests\n -s, --store [store] add variables values to this session (default: [])\n -l, --add-plugin [plugin] add plugin (default: [])\n -a, --add-file <file> add file to be tested (default: [])\n -A, --add-file-and-ignore-others <file> add file to be tested and ignore others (default: [])\n -h, --help output usage information\n\nExamples:\n $ nqr --config-file config-file.yml --verbosity error --store key=value\n $ enqueuer -c config-file.yml test-file.yml --add-file another-test-file.yml -b info\n $ enqueuer test-file.yml --store someKey=true --store someOtherKey=false\n $ nqr --protocols-description -s key=value\n $ nqr -t expect\n $ nqr -l my-enqueuer-plugin-name -p plugin-protocol\n $ nqr -p http\n $ nqr --formatters-description json\n
\n\n
Components
\n
In order to accomplish more than just hitting enqueuer's repo or doing a quick self http hit, there are a few things that you'll probably need to know.\nDon't worry, it's not too much and, as mentioned earlier, there is a lot of examples here, just in case.\nThere are only three important component concepts: requisitions, publishers and subscriptions.\nThey work along with each other and are responsible for the full behavior of enqueuer.
\n
requisition
\n
Test scenario description. It tells what, when, and how test your applications and services.\nPicture it as if it was a collection of publishers, subscriptions and other requisitions.\nIt helps because this is exactly what it is.\nAs the others components, it has some attributes. All of them are optionals. And it supports multi-level test scenarios out of the box. Yeap, go as recursive as you want.\nEvery test file is a requisition.\nYou don't know some of these attributes values yet? Don't worry, just put a variable there and let enqueuer replace it with the value you set later.\nVariable replacements are available through the entire requisition.
\n
requisition attributes
\n
These are the requisition attributes:
\n
name \nDescribes what the requisition is suppose to do.\nDefaults to requisition index.
\n
name: requisition action\n
\n
timeout \nDefaults to 5000.\nSets in milliseconds how long the requisition waits to expire.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
delay \nDefaults to 0. Sets in milliseconds how long the test waits before starting. Check this to get the full idea.
\n
delay: 0\n
\n
iterations \nDefaults to 1. Sets how many times this test will be executed. Check this and this to get the full idea.
\n
iterations: 3\n
\n
ignore \nDefaults to false. Tells to enqueuer that this requisitions should be skipped. Check this to see it working.
\n
ignore: true\n
\n
parallel \nDefaults to false. Immediate children requisitions should be executed in parallel mode.\nTake a look at this to see it working.
\n
parallel: true\n
\n
import \nAllows requisition to be dynamically defined, be it by loading an external file or creating dynamically by other requisitions. Want to reuse the same requisition multiple times? This is you you need.\nTake a look at this to behold this feature.
\n
import: path/to/another/requisition/file\n
\n
publishers \nList of publishers. They're executed simultaneously, therefore, the order is irrelevant.
\n
publishers:\n- name: some publisher name\n type: http\n- type: tcp\n
\n
subscriptions \nList of subscriptions. They're executed simultaneously, therefore, the order is irrelevant.
\n
subscriptions:\n- name: some subscription name\n type: udp\n- name: another subscription name\n type: file\n
\n
requisitions \nA list of child scenarios. List of requisitions.\nBy default, they're executed sequentially, therefore, the order is relevant.\nUnless the parallel attribute is set to true, what makes them get executed simultaneously,\nCheck this example, it may help.
\n
requisitions:\n- name: some requisition name\n iterations: 2\n- name: another requisition name\n delay: 200\n
\n
events
\n
Available events are described here. A this object is available to access and change requisition attributes.
A publisher action is triggered by enqueuer itself. It acts whereas a subscriptionreacts.\nIt publishes something, it writes, it enqueues, hits and endpoint... These kinds of actions.\nIt's worth noting that it always creates a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if the message got published.
\n
publisher attributes
\n
Every publisher has its own properties, depending on its protocol and implementation.\nThe built-in http publisher implementation, for instance, demands a url, a method, and a payload, if the method is not a GET.\nOn the other hand, the built-in tcp publisher implementation requires a serverAddress and a port.\nThese are the publisher attributes:
\n
name \nDefaults to publisher index.\nDescribes what the publisher is supposed to do.
\n
name: publisher action\n
\n
type \nMandatory. Key tag to identify which publisher will be instantiated
\n
type: http\n
\n
payload \nSince a publisher usually publishes something, it's very likely you have to set a value here.\nThe message itself that will be send through this protocol. Be it a string, a number, a boolean value or even whole objects.
\n
payload: value\n
\n
ignore \nDefaults to false. Tells to enqueuer that this publisher should be skipped. Check this to see it working.
\n
ignore: true\n
\n
events
\n
Available events are described here. A this object is available to access and change publisher attributes.\nDepending on the protocol and its implementation, such as http and tcp, there may exist special events, such as onMessageReceived event and a special object given message.\nOn the other hand, an asynchronous protocol, like: udp and amqp, usually do not provide it.
A subscription is an \"under demand\" event. It reacts whereas a publisheracts.\nIt consumes something, it reads, it dequeues, gets hit... These kinds of actions.\nThis means that it is not triggered by enqueuer itself.\nRather than that, enqueuer waits on an external event to be triggered and then it asserts against the message that was passed to the subscription.\nIt's worth noting that it always receives a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if a message got received.
\n
subscription attributes
\n
Every subscription has its own properties, depending on its protocol and implementation.\nThe built-in http subscription implementation, for instance, demands an endpoint, a method, and a port, if the method is not a GET.\nOn the other hand, the built-in tcp subscription implementation requires only a port.
\n
These are the subscription attributes:
\n
name \nDefaults to subscription index.\nDescribes what the subscription is supposed to do.
\n
name: subscription action\n
\n
type \nMandatory. Key tag to identify which subscription will be instantiated
\n
type: http\n
\n
avoid \nIdentifies whether or not this subscription should not receive any message. Defaults to false.\nIf set and a message is received a failing test will be generated.\nTake a look at this to see it working.\nOn the other hand, when it's false and no message is received in a given timeout. The subscription is valid.
\n
avoid: false\n
\n
timeout \nSets in milliseconds how long the subscription waits to expire. Defaults to 3000.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
ignore \nDefaults to false. Tells to enqueuer that this subscription should be skipped. Check this to see it working.
\n
ignore: true \n
\n
events
\n
Available events are described here. A this object is available to access and change subscription attributes.
Events are hook methods executed by enqueuer when an action occurs on publishers, subscriptions or requisitions.\nThis is where you'll write your tests. In its assertions field.\nThere will be a variable called this and, depending on the event's owner, it has an alias publisher, subscription or requisition.\nYou're free to explore them however you want, even doing things like this:
By default, there are three hook events available:
\n
onInit \nAvailable in requisitions, publishers and subscriptions. It gets executed as soon as the component is initialized.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
onFinish \nAvailable in requisitions, publishers and subscriptions. It gets executed when the component is about to finish.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
custom\nDepending on the protocol implementation/library/author's mood, the publisher/subscription may have additional hooks.\nSuch as onError, onResponseReceived, onFileNotFound and onRedirect...\nHttp-proxy subscription test file is an excellent example, check it out.
\n
fields
\n
Every hook object has 3 properties:
\n
script \nJavascript code snippet executed when the event is triggered.\nYeah, I mean it. See it it by yourself.\nBut be careful, with great power comes great responsibility.
\n
store \nData to be persisted across requisitions.
\n
assertions \nArray of assertions.\nRun $ nqr -t to see available ones.\nConsider looking at this test example.\nOf course, just like almost everything else in enqueuer world, you can extend this available list using some plugin.\nYou can check them out or even write your own.
Now that you know what are requisitions, publishers, subscriptions and events. How about seeing how they interact with each other in a fancier way?
\n
\n\n
Configuration File
\n
To save yourself some time, a configuration file may be used.\nConfiguration files tell enqueuer which tests will be executed, log-level, and which output test report files should be generated.\nThis file tells how enqueuer should be executed.\nTo run enqueuer with the configuration:
files \nRequisition file names or glob. Enqueuer runs every file that matches an element value.
\n
files:\n- 1.yml\n- 2.yml\n- *.json\n
\n
parallel \nDefaults to false. Requisition files should be executed in parallel mode. The requisition file itself is still sequential, but the files are executes in parallel.
\n
parallel: true\n
\n
log-level \nDefaults to warning. Defines how information are logged in the console. Accepted values are: trace; debug; info; warning (default); error; and fatal.
\n
log-level: trace\n
\n
max-report-level-print \nDefaults to 1. The deepest level of report to be printed to the console.
outputs \nOnce enqueuer runs every execution, it compiles a summary and sends it to every publisher listed in output.\nAn important thing to note is that every available report publisher is available here.\nYes, it means that you are able to send this report through http, tcp, etc. or through a plugin one or a custom one.\nYou can run $ nqr -p to check available report publishers installed.\nAnother important thing to note is the format value. By default a json summary is generated, but you can change it to whatever format you would like, such as: Xunit, html\nYou can run $ nqr -f to check available installed formats or even write your own
store \nValues defined here use the 'key: value' pattern and are available to every test scenario throughout the entire execution
\n
store:\n variableKey: \"my value\" # Defines 'variableKey' key and its value 'my value'. \n \n 'separated key': 6\n \n object: # You can even define whole objects here:\n first: first value\n second:\n nested: thing\n
\n
example
\n
Here's a complete example of a configuration file.
\n\n
Variables
\n
Providing power and flexibility, enqueuer allows you to use variables placeholder replacement.\nThat's why there is a store field and you'll see a lot of << and {{ being used in the examples files.\nIt works as simple as this:
\n
name: my name is <<variableKey>>\n
\n
Every time enqueuer sees these kind of notations, it searches in its store for a key/value pair like:
\n
variableKey: `enqueuer`\n
\n
Then, when enqueuer parses the original map, it gets translated to this:
\n
name: my name is enqueuer\n
\n
By default, every ENV_VAR set is loaded automatically to the store. Check this example.
\n
set a variable
\n
There are a few ways to set a value in the store.
\n
configuration file
\n
Configuration file store object. Set it as you wish, as you can see here
\n
command line
\n
A command line argument using the key=value format. This way:
\n
$ nqr --store key=value -s anotherVariable=true\n
\n
event
\n
Dynamically set it through any event.\nBe it in its script field or straight through its store field.\nBoth ways work:
The easiest one is to type <<variableKey>> or {{variableKey}} where you want it to be replaced in a test file, as you can see here
\n
js code snippet
\n
Using the store object. It's attributes are the keys and their values are their respective values.\nTherefore, you're free to use store.variableKey, console.log(store.variableKey); or console.log(2 * store['separated key']); and get them.\nLike this one.
It get's event better.\nDue its fantastic plugin architecture design, you can extend its default modules and use any of these plugins or event write your own to parse however you want.\nThe built-in modules for object parsers are: json, yml, csv and file.\nRun $ nqr -e to see available ones.
You're probably aware by now but it doesn't hurt do emphasize it: enqueuer provides an amazingly powerful plugin extensible architecture.\nIt has several plugins available, but if none of them pleases you, you're free to create your own.\nAlbeit you don't have to share the one you created, we encourage you to do so. Then go ahead and publish yours to npm and add it to our plugins list.
\n
plugin types
\n
So far, you're able to extend enqueuer default behavior in four ways. Using a protocol plugin, an object parser plugin, an asserter plugin and using a report formatter plugin.
\n
protocol
\n
A protocol plugin enables you to use a different publisher/subscription types.\nRun $ nqr -p [protocol-name] to get the full available list:
Each one listed above has a respective example in the examples folder.\nThis one, for instance, provides support for amqp protocol, so you can create this publisher and subscription:
An object parser plugin enables you to read and parse files as you wish.\nThis test example demonstrates how to use it,\nRun $ nqr -e [object-parser-name] to check available ones:
\n
parsers: \n- yml, yaml\n- json\n- file\n- csv\n
\n
This one, for example, provides the ability to read xml files and inject their values like this:
\n
xmlContent: <<xml://path/to/xml/file.xml>>\n
\n
asserter
\n
An asserter plugin provides you a nicely way to use different assertions than these built-in ones.
Run $ nqr -t to get the full available list.\nConsider looking at this test example.
\n
report formatter
\n
A report formatter plugin gives you the ability to export enqueuer reports the way you want.\nRun $ nqr -f [formatter-name] to list available report formatters:
Consider looking at the example of configuration file to see it in use.\nThis one, for instance, generates xUnit like reports from enqueuer's output.
\n
plugin installation
\n
In order to enqueuer get awareness that you want to use a plugin, you have to tell it, right?\nYou can tell enqueuer to use a plugin in three different ways: using it as a command line argument, through the configuration file or letting enqueuer finding it in a default location.
\n
command line
\n
Tell enqueuer to use your plugin through command line this way $ nqr -l <plugin-folder> -l <another-plugin-folder>.\nWhere plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
configuration file
\n
Tell enqueuer to use your plugin through configuration file this way:
Where plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
implicitly
\n
When enqueuer runs, it looks for modules in its same installation directory or in .nqr folder in the home directory, a.k.a. ~/ folder in linux distributions.\nTherefore, if you run:
You'll see that the enqueuer-plugin-amqp plugin will be loaded.\nEvery enqueuer compatible module gets implicitly loaded.\nIn order to be enqueuer compatible, a module has to have an entryPoint exported function in its main file and, in its package.json file, it has to have either 'enqueuer' or 'nqr' as keywords.
\n
Stacker
\n
Looking for a really really good looking an human error proof solution way of writing these requisition files? \nConsider taking a look at stacker: open source, cross-platform, multi protocol client testing tool.\nThe official enqueuer's best friend forever. Do amazing things and change the world with enqueuer’s GUI!\nWith them, you create, manage and run requisitions and and see their results in a really nice way.\nSee this amazing beauty with your own eyes to get an idea of how it works:
\n
\n\n
Open source
\n
We (by 'we' we mean enqueuer's maintainers not the human race, unfortunately) are very opened to any kind of contributions in general.\nAs long as they make sense and add value to the product, you're free to go.\nWe mean it, do it. Even if it's a typo fix in this README file. Go ahead.\nIf you like it but don't want to waste time creating a pull request, no problem either.\nCreate an issue, or, even easier, give it a github star. It's cheap and it doesn't hurt anyone.\nYou know what? Just head up to enqueuer's github repo and keep staring at its repo.\nIt may help somehow.
In order to contribute with some code, you have to follow a few steps.\nFirst of all, get the code:
\n
$ git clone git@github.com:enqueuer-land/enqueuer.git\n$ cd enqueuer\n
\n
Get its dependencies installed:
\n
$ npm install\n
\n
Build it:
\n
$ npm run build\n
\n
Go for it. Make the changes you want.\nAfter everything is done:
\n
$ npm run all\n
\n
Commit it:
\n
$ npm run commit\n
\n
Push it:
\n
$ git push\n
\n
feedback
\n
We'd love to get your feedback!\nIf you have any comments, suggestions, etc. you can reach us here.
\n
\n\n
\n
\n\n\n\n
\n
\n\n \n
\n \n\n
\n\n \n\n\n\n\n
\n \n \n You can’t perform that action at this time.\n
\n\n\n \n \n \n \n \n \n \n
\n \n You signed in with another tab or window. Reload to refresh your session.\n You signed out in another tab or window. Reload to refresh your session.\n
\n Over 40 million developers use GitHub together\n to host and review code, project manage, and build software together\n across more than 100 million projects.\n
Now go ahead and try hitting it using the browser.\nTip: remove timeout values and check what happens.\nI told you it was simple.\nNow, let's say you want to mix different protocols to test a bit more complex flow.\nHow about publishing an amqp message and making sure that, once a service consumes that message an endpoint of your is hit?\nIn order to achieve that, we have to make use of a plugin, given that amqp support is provided by a plugin.\nIn this scenario, we're talking about the amqp plugin.\nOnce we get this plugin installed we are able to create and run files like this:
Now go nuts!\nIt's all yours. Have fun.\nIf you want more examples about http, consider looking at this test.\nCheck this out, you'll find countless examples.\nCertainly one is what you need.
\n
if you need more
\n
$ nqr -h\nUsage: nqr [options] <test-file> [other-test-files...]\n\nTake a look at the full documentation: https://enqueuer.com\n\nOptions:\n -v, --version output the version number\n -b, --verbosity <level> set verbosity (default: \"warn\")\n -c, --config-file <path> set configurationFile\n -e, --parsers-list [parser] list available object parsers\n -f, --formatters-description [formatter] describe report formatters\n -o, --stdout-requisition-output add stdout as requisition output\n -m, --max-report-level-print <level> set max report level print\n -p, --protocols-description [protocol] describe protocols\n -t, --tests-list [expectedField] list available tests assertions\n -u, --loaded-modules-list list loaded modules\n -i, --show-passing-tests show passing tests\n -s, --store [store] add variables values to this session (default: [])\n -l, --add-plugin [plugin] add plugin (default: [])\n -a, --add-file <file> add file to be tested (default: [])\n -A, --add-file-and-ignore-others <file> add file to be tested and ignore others (default: [])\n -h, --help output usage information\n\nExamples:\n $ nqr --config-file config-file.yml --verbosity error --store key=value\n $ enqueuer -c config-file.yml test-file.yml --add-file another-test-file.yml -b info\n $ enqueuer test-file.yml --store someKey=true --store someOtherKey=false\n $ nqr --protocols-description -s key=value\n $ nqr -t expect\n $ nqr -l my-enqueuer-plugin-name -p plugin-protocol\n $ nqr -p http\n $ nqr --formatters-description json\n \nContributing:\n https://github.com/enqueuer-land/enqueuer\n
\n\n
Components
\n
In order to accomplish more than just hitting enqueuer's repo or doing a quick self http hit, there are a few things that you'll probably need to know.\nDon't worry, it's not too much and, as mentioned earlier, there is a lot of examples here, just in case.\nThere are only three important component concepts: requisitions, publishers and subscriptions.\nThey work along with each other and are responsible for the full behavior of enqueuer.
\n
requisition
\n
Test scenario description. It tells what, when, and how test your applications and services.\nPicture it as if it was a collection of publishers, subscriptions and other requisitions.\nIt helps because this is exactly what it is.\nAs the others components, it has some attributes. All of them are optionals. And it supports multi-level test scenarios out of the box. Yeap, go as recursive as you want.\nEvery test file is a requisition.\nYou don't know some of these attributes values yet? Don't worry, just put a variable there and let enqueuer replace it with the value you set later.\nVariable replacements are available through the entire requisition.
\n
requisition attributes
\n
These are the requisition attributes:
\n
name \nDescribes what the requisition is suppose to do.\nDefaults to requisition index.
\n
name: requisition action\n
\n
timeout \nDefaults to 5000.\nSets in milliseconds how long the requisition waits to expire.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
delay \nDefaults to 0. Sets in milliseconds how long the test waits before starting. Check this to get the full idea.
\n
delay: 0\n
\n
iterations \nDefaults to 1. Sets how many times this test will be executed. Check this and this to get the full idea.
\n
iterations: 3\n
\n
ignore \nDefaults to false. Tells to enqueuer that this requisitions should be skipped. Check this to see it working.
\n
ignore: true\n
\n
parallel \nDefaults to false. Immediate children requisitions should be executed in parallel mode.\nTake a look at this to see it working.
\n
parallel: true\n
\n
import \nAllows requisition to be dynamically defined, be it by loading an external file or creating dynamically by other requisitions. Want to reuse the same requisition multiple times? This is you you need.\nTake a look at this to behold this feature.
\n
import: path/to/another/requisition/file\n
\n
publishers \nList of publishers. They're executed simultaneously, therefore, the order is irrelevant.
\n
publishers:\n- name: some publisher name\n type: http\n- type: tcp\n
\n
subscriptions \nList of subscriptions. They're executed simultaneously, therefore, the order is irrelevant.
\n
subscriptions:\n- name: some subscription name\n type: udp\n- name: another subscription name\n type: file\n
\n
requisitions \nA list of child scenarios. List of requisitions.\nBy default, they're executed sequentially, therefore, the order is relevant.\nUnless the parallel attribute is set to true, what makes them get executed simultaneously,\nCheck this example, it may help.
\n
requisitions:\n- name: some requisition name\n iterations: 2\n- name: another requisition name\n delay: 200\n
\n
events
\n
Available events are described here. A this object is available to access and change requisition attributes.
A publisher action is triggered by enqueuer itself. It acts whereas a subscriptionreacts.\nIt publishes something, it writes, it enqueues, hits and endpoint... These kinds of actions.\nIt's worth noting that it always creates a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if the message got published.
\n
publisher attributes
\n
Every publisher has its own properties, depending on its protocol and implementation.\nThe built-in http publisher implementation, for instance, demands a url, a method, and a payload, if the method is not a GET.\nOn the other hand, the built-in tcp publisher implementation requires a serverAddress and a port.\nThese are the publisher attributes:
\n
name \nDefaults to publisher index.\nDescribes what the publisher is supposed to do.
\n
name: publisher action\n
\n
type \nMandatory. Key tag to identify which publisher will be instantiated
\n
type: http\n
\n
payload \nSince a publisher usually publishes something, it's very likely you have to set a value here.\nThe message itself that will be send through this protocol. Be it a string, a number, a boolean value or even whole objects.
\n
payload: value\n
\n
ignore \nDefaults to false. Tells to enqueuer that this publisher should be skipped. Check this to see it working.
\n
ignore: true\n
\n
events
\n
Available events are described here. A this object is available to access and change publisher attributes.\nDepending on the protocol and its implementation, such as http and tcp, there may exist special events, such as onMessageReceived event and a special object given message.\nOn the other hand, an asynchronous protocol, like: udp and amqp, usually do not provide it.
A subscription is an \"under demand\" event. It reacts whereas a publisheracts.\nIt consumes something, it reads, it dequeues, gets hit... These kinds of actions.\nThis means that it is not triggered by enqueuer itself.\nRather than that, enqueuer waits on an external event to be triggered and then it asserts against the message that was passed to the subscription.\nIt's worth noting that it always receives a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if a message got received.
\n
subscription attributes
\n
Every subscription has its own properties, depending on its protocol and implementation.\nThe built-in http subscription implementation, for instance, demands an endpoint, a method, and a port, if the method is not a GET.\nOn the other hand, the built-in tcp subscription implementation requires only a port.
\n
These are the subscription attributes:
\n
name \nDefaults to subscription index.\nDescribes what the subscription is supposed to do.
\n
name: subscription action\n
\n
type \nMandatory. Key tag to identify which subscription will be instantiated
\n
type: http\n
\n
avoid \nIdentifies whether or not this subscription should not receive any message. Defaults to false.\nIf set and a message is received a failing test will be generated.\nTake a look at this to see it working.\nOn the other hand, when it's false and no message is received in a given timeout. The subscription is valid.
\n
avoid: false\n
\n
timeout \nSets in milliseconds how long the subscription waits to expire. Defaults to 3000.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
ignore \nDefaults to false. Tells to enqueuer that this subscription should be skipped. Check this to see it working.
\n
ignore: true \n
\n
events
\n
Available events are described here. A this object is available to access and change subscription attributes.
Events are hook methods executed by enqueuer when an action occurs on publishers, subscriptions or requisitions.\nThis is where you'll write your tests. In its assertions field.\nThere will be a variable called this and, depending on the event's owner, it has an alias publisher, subscription or requisition.\nYou're free to explore them however you want, even doing things like this:
By default, there are three hook events available:
\n
onInit \nAvailable in requisitions, publishers and subscriptions. It gets executed as soon as the component is initialized.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
onFinish \nAvailable in requisitions, publishers and subscriptions. It gets executed when the component is about to finish.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
custom\nDepending on the protocol implementation/library/author's mood, the publisher/subscription may have additional hooks.\nSuch as onError, onResponseReceived, onFileNotFound and onRedirect...\nHttp-proxy subscription test file is an excellent example, check it out.
\n
fields
\n
Every hook object has 3 properties:
\n
script \nJavascript code snippet executed when the event is triggered.\nYeah, I mean it. See it it by yourself.\nBut be careful, with great power comes great responsibility.
\n
store \nData to be persisted across requisitions.
\n
assertions \nArray of assertions.\nRun $ nqr -t to see available ones.\nConsider looking at this test example.\nOf course, just like almost everything else in enqueuer world, you can extend this available list using some plugin.\nYou can check them out or even write your own.
Now that you know what are requisitions, publishers, subscriptions and events. How about seeing how they interact with each other in a fancier way?
\n
\n\n
Configuration File
\n
To save yourself some time, a configuration file may be used.\nConfiguration files tell enqueuer which tests will be executed, log-level, and which output test report files should be generated.\nThis file tells how enqueuer should be executed.\nTo run enqueuer with the configuration:
files \nRequisition file names or glob. Enqueuer runs every file that matches an element value.
\n
files:\n- 1.yml\n- 2.yml\n- *.json\n
\n
parallel \nDefaults to false. Requisition files should be executed in parallel mode. The requisition file itself is still sequential, but the files are executes in parallel.
\n
parallel: true\n
\n
log-level \nDefaults to warning. Defines how information are logged in the console. Accepted values are: trace; debug; info; warning (default); error; and fatal.
\n
log-level: trace\n
\n
max-report-level-print \nDefaults to 1. The deepest level of report to be printed to the console.
outputs \nOnce enqueuer runs every execution, it compiles a summary and sends it to every publisher listed in output.\nAn important thing to note is that every available report publisher is available here.\nYes, it means that you are able to send this report through http, tcp, etc. or through a plugin one or a custom one.\nYou can run $ nqr -p to check available report publishers installed.\nAnother important thing to note is the format value. By default a json summary is generated, but you can change it to whatever format you would like, such as: Xunit, html\nYou can run $ nqr -f to check available installed formats or even write your own
store \nValues defined here use the 'key: value' pattern and are available to every test scenario throughout the entire execution
\n
store:\n variableKey: \"my value\" # Defines 'variableKey' key and its value 'my value'. \n \n 'separated key': 6\n \n object: # You can even define whole objects here:\n first: first value\n second:\n nested: thing\n
\n
example
\n
Here's a complete example of a configuration file.
\n\n
Variables
\n
Providing power and flexibility, enqueuer allows you to use variables placeholder replacement.\nThat's why there is a store field and you'll see a lot of << and {{ being used in the examples files.\nIt works as simple as this:
\n
name: my name is <<variableKey>>\n
\n
Every time enqueuer sees these kind of notations, it searches in its store for a key/value pair like:
\n
variableKey: `enqueuer`\n
\n
Then, when enqueuer parses the original map, it gets translated to this:
\n
name: my name is enqueuer\n
\n
By default, every ENV_VAR set is loaded automatically to the store. Check this example.
\n
set a variable
\n
There are a few ways to set a value in the store.
\n
configuration file
\n
Configuration file store object. Set it as you wish, as you can see here
\n
command line
\n
A command line argument using the key=value format. This way:
\n
$ nqr --store key=value -s anotherVariable=true\n
\n
event
\n
Dynamically set it through any event.\nBe it in its script field or straight through its store field.\nBoth ways work:
The easiest one is to type <<variableKey>> or {{variableKey}} where you want it to be replaced in a test file, as you can see here
\n
js code snippet
\n
Using the store object. It's attributes are the keys and their values are their respective values.\nTherefore, you're free to use store.variableKey, console.log(store.variableKey); or console.log(2 * store['separated key']); and get them.\nLike this one.
It get's event better.\nDue its fantastic plugin architecture design, you can extend its default modules and use any of these plugins or event write your own to parse however you want.\nThe built-in modules for object parsers are: json, yml, csv and file.\nRun $ nqr -e to see available ones.
You're probably aware by now but it doesn't hurt do emphasize it: enqueuer provides an amazingly powerful plugin extensible architecture.\nIt has several plugins available, but if none of them pleases you, you're free to create your own.\nAlbeit you don't have to share the one you created, we encourage you to do so. Then go ahead and publish yours to npm and add it to our plugins list.
\n
plugin types
\n
So far, you're able to extend enqueuer default behavior in four ways. Using a protocol plugin, an object parser plugin, an asserter plugin and using a report formatter plugin.
\n
protocol
\n
A protocol plugin enables you to use a different publisher/subscription types.\nRun $ nqr -p [protocol-name] to get the full available list:
Each one listed above has a respective example in the examples folder.\nThis one, for instance, provides support for amqp protocol, so you can create this publisher and subscription:
An object parser plugin enables you to read and parse files as you wish.\nThis test example demonstrates how to use it,\nRun $ nqr -e [object-parser-name] to check available ones:
\n
parsers: \n- yml, yaml\n- json\n- file\n- csv\n
\n
This one, for example, provides the ability to read xml files and inject their values like this:
\n
xmlContent: <<xml://path/to/xml/file.xml>>\n
\n
asserter
\n
An asserter plugin provides you a nicely way to use different assertions than these built-in ones.
Run $ nqr -t to get the full available list.\nConsider looking at this test example.
\n
report formatter
\n
A report formatter plugin gives you the ability to export enqueuer reports the way you want.\nRun $ nqr -f [formatter-name] to list available report formatters:
Consider looking at the example of configuration file to see it in use.\nThis one, for instance, generates xUnit like reports from enqueuer's output.
\n
plugin installation
\n
In order to enqueuer get awareness that you want to use a plugin, you have to tell it, right?\nYou can tell enqueuer to use a plugin in three different ways: using it as a command line argument, through the configuration file or letting enqueuer finding it in a default location.
\n
command line
\n
Tell enqueuer to use your plugin through command line this way $ nqr -l <plugin-folder> -l <another-plugin-folder>.\nWhere plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
configuration file
\n
Tell enqueuer to use your plugin through configuration file this way:
Where plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
implicitly
\n
When enqueuer runs, it looks for modules in its same installation directory or in .nqr folder in the home directory, a.k.a. ~/ folder in linux distributions.\nTherefore, if you run:
You'll see that the enqueuer-plugin-amqp plugin will be loaded.\nEvery enqueuer compatible module gets implicitly loaded.\nIn order to be enqueuer compatible, a module has to have an entryPoint exported function in its main file and, in its package.json file, it has to have either 'enqueuer' or 'nqr' as keywords.
\n
Stacker
\n
Looking for a really really good looking an human error proof solution way of writing these requisition files? \nConsider taking a look at stacker: open source, cross-platform, multi protocol client testing tool.\nThe official enqueuer's best friend forever. Do amazing things and change the world with enqueuer’s GUI!\nWith them, you create, manage and run requisitions and and see their results in a really nice way.\nSee this amazing beauty with your own eyes to get an idea of how it works:
\n
\n\n
Open source
\n
We (by 'we' we mean enqueuer's maintainers not the human race, unfortunately) are very opened to any kind of contributions in general.\nAs long as they make sense and add value to the product, you're free to go.\nWe mean it, do it. Even if it's a typo fix in this README file. Go ahead.\nIf you like it but don't want to waste time creating a pull request, no problem either.\nCreate an issue, or, even easier, give it a github star. It's cheap and it doesn't hurt anyone.\nYou know what? Just head up to enqueuer's github repo and keep staring at its repo.\nIt may help somehow.
In order to contribute with some code, you have to follow a few steps.\nFirst of all, get the code:
\n
$ git clone git@github.com:enqueuer-land/enqueuer.git\n$ cd enqueuer\n
\n
Get its dependencies installed:
\n
$ npm install\n
\n
Build it:
\n
$ npm run build\n
\n
Go for it. Make the changes you want.\nAfter everything is done:
\n
$ npm run all\n
\n
Commit it:
\n
$ npm run commit\n
\n
Push it:
\n
$ git push\n
\n
feedback
\n
We'd love to get your feedback!\nIf you have any comments, suggestions, etc. you can reach us here.
\n
\n\n
\n
\n\n\n\n\n
\n
\n\n \n
\n \n\n
\n\n \n\n\n\n\n
\n \n \n You can’t perform that action at this time.\n
\n\n\n \n \n \n \n \n \n \n
\n \n You signed in with another tab or window. Reload to refresh your session.\n You signed out in another tab or window. Reload to refresh your session.\n
Now go ahead and try hitting it using the browser.\nTip: remove timeout values and check what happens.\nI told you it was simple.\nNow, let's say you want to mix different protocols to test a bit more complex flow.\nHow about publishing an amqp message and making sure that, once a service consumes that message an endpoint of your is hit?\nIn order to achieve that, we have to make use of a plugin, given that amqp support is provided by a plugin.\nIn this scenario, we're talking about the amqp plugin.\nOnce we get this plugin installed we are able to create and run files like this:
Now go nuts!\nIt's all yours. Have fun.\nIf you want more examples about http, consider looking at this test.\nCheck this out, you'll find countless examples.\nCertainly one is what you need.
\n
if you need more
\n
$ nqr -h\nUsage: nqr [options] <test-file> [other-test-files...]\n\nTake a look at the full documentation: https://enqueuer.com\n\nOptions:\n -v, --version output the version number\n -b, --verbosity <level> set verbosity (default: \"warn\")\n -c, --config-file <path> set configurationFile\n -e, --parsers-list [parser] list available object parsers\n -f, --formatters-description [formatter] describe report formatters\n -o, --stdout-requisition-output add stdout as requisition output\n -m, --max-report-level-print <level> set max report level print\n -p, --protocols-description [protocol] describe protocols\n -t, --tests-list [expectedField] list available tests assertions\n -u, --loaded-modules-list list loaded modules\n -i, --show-passing-tests show passing tests\n -s, --store [store] add variables values to this session (default: [])\n -l, --add-plugin [plugin] add plugin (default: [])\n -a, --add-file <file> add file to be tested (default: [])\n -A, --add-file-and-ignore-others <file> add file to be tested and ignore others (default: [])\n -h, --help output usage information\n\nExamples:\n $ nqr --config-file config-file.yml --verbosity error --store key=value\n $ enqueuer -c config-file.yml test-file.yml --add-file another-test-file.yml -b info\n $ enqueuer test-file.yml --store someKey=true --store someOtherKey=false\n $ nqr --protocols-description -s key=value\n $ nqr -t expect\n $ nqr -l my-enqueuer-plugin-name -p plugin-protocol\n $ nqr -p http\n $ nqr --formatters-description json\n
\n\n
Components
\n
In order to accomplish more than just hitting enqueuer's repo or doing a quick self http hit, there are a few things that you'll probably need to know.\nDon't worry, it's not too much and, as mentioned earlier, there is a lot of examples here, just in case.\nThere are only three important component concepts: requisitions, publishers and subscriptions.\nThey work along with each other and are responsible for the full behavior of enqueuer.
\n
requisition
\n
Test scenario description. It tells what, when, and how test your applications and services.\nPicture it as if it was a collection of publishers, subscriptions and other requisitions.\nIt helps because this is exactly what it is.\nAs the others components, it has some attributes. All of them are optionals. And it supports multi-level test scenarios out of the box. Yeap, go as recursive as you want.\nEvery test file is a requisition.\nYou don't know some of these attributes values yet? Don't worry, just put a variable there and let enqueuer replace it with the value you set later.\nVariable replacements are available through the entire requisition.
\n
requisition attributes
\n
These are the requisition attributes:
\n
name \nDescribes what the requisition is suppose to do.\nDefaults to requisition index.
\n
name: requisition action\n
\n
timeout \nDefaults to 5000.\nSets in milliseconds how long the requisition waits to expire.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
delay \nDefaults to 0. Sets in milliseconds how long the test waits before starting. Check this to get the full idea.
\n
delay: 0\n
\n
iterations \nDefaults to 1. Sets how many times this test will be executed. Check this and this to get the full idea.
\n
iterations: 3\n
\n
ignore \nDefaults to false. Tells to enqueuer that this requisitions should be skipped. Check this to see it working.
\n
ignore: true\n
\n
parallel \nDefaults to false. Immediate children requisitions should be executed in parallel mode.\nTake a look at this to see it working.
\n
parallel: true\n
\n
import \nAllows requisition to be dynamically defined, be it by loading an external file or creating dynamically by other requisitions. Want to reuse the same requisition multiple times? This is you you need.\nTake a look at this to behold this feature.
\n
import: path/to/another/requisition/file\n
\n
publishers \nList of publishers. They're executed simultaneously, therefore, the order is irrelevant.
\n
publishers:\n- name: some publisher name\n type: http\n- type: tcp\n
\n
subscriptions \nList of subscriptions. They're executed simultaneously, therefore, the order is irrelevant.
\n
subscriptions:\n- name: some subscription name\n type: udp\n- name: another subscription name\n type: file\n
\n
requisitions \nA list of child scenarios. List of requisitions.\nBy default, they're executed sequentially, therefore, the order is relevant.\nUnless the parallel attribute is set to true, what makes them get executed simultaneously,\nCheck this example, it may help.
\n
requisitions:\n- name: some requisition name\n iterations: 2\n- name: another requisition name\n delay: 200\n
\n
events
\n
Available events are described here. A this object is available to access and change requisition attributes.
A publisher action is triggered by enqueuer itself. It acts whereas a subscriptionreacts.\nIt publishes something, it writes, it enqueues, hits and endpoint... These kinds of actions.\nIt's worth noting that it always creates a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if the message got published.
\n
publisher attributes
\n
Every publisher has its own properties, depending on its protocol and implementation.\nThe built-in http publisher implementation, for instance, demands a url, a method, and a payload, if the method is not a GET.\nOn the other hand, the built-in tcp publisher implementation requires a serverAddress and a port.\nThese are the publisher attributes:
\n
name \nDefaults to publisher index.\nDescribes what the publisher is supposed to do.
\n
name: publisher action\n
\n
type \nMandatory. Key tag to identify which publisher will be instantiated
\n
type: http\n
\n
payload \nSince a publisher usually publishes something, it's very likely you have to set a value here.\nThe message itself that will be send through this protocol. Be it a string, a number, a boolean value or even whole objects.
\n
payload: value\n
\n
ignore \nDefaults to false. Tells to enqueuer that this publisher should be skipped. Check this to see it working.
\n
ignore: true\n
\n
events
\n
Available events are described here. A this object is available to access and change publisher attributes.\nDepending on the protocol and its implementation, such as http and tcp, there may exist special events, such as onMessageReceived event and a special object given message.\nOn the other hand, an asynchronous protocol, like: udp and amqp, usually do not provide it.
A subscription is an \"under demand\" event. It reacts whereas a publisheracts.\nIt consumes something, it reads, it dequeues, gets hit... These kinds of actions.\nThis means that it is not triggered by enqueuer itself.\nRather than that, enqueuer waits on an external event to be triggered and then it asserts against the message that was passed to the subscription.\nIt's worth noting that it always receives a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if a message got received.
\n
subscription attributes
\n
Every subscription has its own properties, depending on its protocol and implementation.\nThe built-in http subscription implementation, for instance, demands an endpoint, a method, and a port, if the method is not a GET.\nOn the other hand, the built-in tcp subscription implementation requires only a port.
\n
These are the subscription attributes:
\n
name \nDefaults to subscription index.\nDescribes what the subscription is supposed to do.
\n
name: subscription action\n
\n
type \nMandatory. Key tag to identify which subscription will be instantiated
\n
type: http\n
\n
avoid \nIdentifies whether or not this subscription should not receive any message. Defaults to false.\nIf set and a message is received a failing test will be generated.\nTake a look at this to see it working.\nOn the other hand, when it's false and no message is received in a given timeout. The subscription is valid.
\n
avoid: false\n
\n
timeout \nSets in milliseconds how long the subscription waits to expire. Defaults to 3000.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
ignore \nDefaults to false. Tells to enqueuer that this subscription should be skipped. Check this to see it working.
\n
ignore: true \n
\n
events
\n
Available events are described here. A this object is available to access and change subscription attributes.
Events are hook methods executed by enqueuer when an action occurs on publishers, subscriptions or requisitions.\nThis is where you'll write your tests. In its assertions field.\nThere will be a variable called this and, depending on the event's owner, it has an alias publisher, subscription or requisition.\nYou're free to explore them however you want, even doing things like this:
By default, there are three hook events available:
\n
onInit \nAvailable in requisitions, publishers and subscriptions. It gets executed as soon as the component is initialized.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
onFinish \nAvailable in requisitions, publishers and subscriptions. It gets executed when the component is about to finish.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
custom\nDepending on the protocol implementation/library/author's mood, the publisher/subscription may have additional hooks.\nSuch as onError, onResponseReceived, onFileNotFound and onRedirect...\nHttp-proxy subscription test file is an excellent example, check it out.
\n
fields
\n
Every hook object has 3 properties:
\n
script \nJavascript code snippet executed when the event is triggered.\nYeah, I mean it. See it it by yourself.\nBut be careful, with great power comes great responsibility.
\n
store \nData to be persisted across requisitions.
\n
assertions \nArray of assertions.\nRun $ nqr -t to see available ones.\nConsider looking at this test example.\nOf course, just like almost everything else in enqueuer world, you can extend this available list using some plugin.\nYou can check them out or even write your own.
Now that you know what are requisitions, publishers, subscriptions and events. How about seeing how they interact with each other in a fancier way?
\n
\n\n
Configuration File
\n
To save yourself some time, a configuration file may be used.\nConfiguration files tell enqueuer which tests will be executed, log-level, and which output test report files should be generated.\nThis file tells how enqueuer should be executed.\nTo run enqueuer with the configuration:
files \nRequisition file names or glob. Enqueuer runs every file that matches an element value.
\n
files:\n- 1.yml\n- 2.yml\n- *.json\n
\n
parallel \nDefaults to false. Requisition files should be executed in parallel mode. The requisition file itself is still sequential, but the files are executes in parallel.
\n
parallel: true\n
\n
log-level \nDefaults to warning. Defines how information are logged in the console. Accepted values are: trace; debug; info; warning (default); error; and fatal.
\n
log-level: trace\n
\n
max-report-level-print \nDefaults to 1. The deepest level of report to be printed to the console.
outputs \nOnce enqueuer runs every execution, it compiles a summary and sends it to every publisher listed in output.\nAn important thing to note is that every available report publisher is available here.\nYes, it means that you are able to send this report through http, tcp, etc. or through a plugin one or a custom one.\nYou can run $ nqr -p to check available report publishers installed.\nAnother important thing to note is the format value. By default a json summary is generated, but you can change it to whatever format you would like, such as: Xunit, html\nYou can run $ nqr -f to check available installed formats or even write your own
store \nValues defined here use the 'key: value' pattern and are available to every test scenario throughout the entire execution
\n
store:\n variableKey: \"my value\" # Defines 'variableKey' key and its value 'my value'. \n \n 'separated key': 6\n \n object: # You can even define whole objects here:\n first: first value\n second:\n nested: thing\n
\n
example
\n
Here's a complete example of a configuration file.
\n\n
Variables
\n
Providing power and flexibility, enqueuer allows you to use variables placeholder replacement.\nThat's why there is a store field and you'll see a lot of << and {{ being used in the examples files.\nIt works as simple as this:
\n
name: my name is <<variableKey>>\n
\n
Every time enqueuer sees these kind of notations, it searches in its store for a key/value pair like:
\n
variableKey: `enqueuer`\n
\n
Then, when enqueuer parses the original map, it gets translated to this:
\n
name: my name is enqueuer\n
\n
By default, every ENV_VAR set is loaded automatically to the store. Check this example.
\n
set a variable
\n
There are a few ways to set a value in the store.
\n
configuration file
\n
Configuration file store object. Set it as you wish, as you can see here
\n
command line
\n
A command line argument using the key=value format. This way:
\n
$ nqr --store key=value -s anotherVariable=true\n
\n
event
\n
Dynamically set it through any event.\nBe it in its script field or straight through its store field.\nBoth ways work:
The easiest one is to type <<variableKey>> or {{variableKey}} where you want it to be replaced in a test file, as you can see here
\n
js code snippet
\n
Using the store object. It's attributes are the keys and their values are their respective values.\nTherefore, you're free to use store.variableKey, console.log(store.variableKey); or console.log(2 * store['separated key']); and get them.\nLike this one.
It get's event better.\nDue its fantastic plugin architecture design, you can extend its default modules and use any of these plugins or event write your own to parse however you want.\nThe built-in modules for object parsers are: json, yml, csv and file.\nRun $ nqr -e to see available ones.
You're probably aware by now but it doesn't hurt do emphasize it: enqueuer provides an amazingly powerful plugin extensible architecture.\nIt has several plugins available, but if none of them pleases you, you're free to create your own.\nAlbeit you don't have to share the one you created, we encourage you to do so. Then go ahead and publish yours to npm and add it to our plugins list.
\n
plugin types
\n
So far, you're able to extend enqueuer default behavior in four ways. Using a protocol plugin, an object parser plugin, an asserter plugin and using a report formatter plugin.
\n
protocol
\n
A protocol plugin enables you to use a different publisher/subscription types.\nRun $ nqr -p [protocol-name] to get the full available list:
Each one listed above has a respective example in the examples folder.\nThis one, for instance, provides support for amqp protocol, so you can create this publisher and subscription:
An object parser plugin enables you to read and parse files as you wish.\nThis test example demonstrates how to use it,\nRun $ nqr -e [object-parser-name] to check available ones:
\n
parsers: \n- yml, yaml\n- json\n- file\n- csv\n
\n
This one, for example, provides the ability to read xml files and inject their values like this:
\n
xmlContent: <<xml://path/to/xml/file.xml>>\n
\n
asserter
\n
An asserter plugin provides you a nicely way to use different assertions than these built-in ones.
Run $ nqr -t to get the full available list.\nConsider looking at this test example.
\n
report formatter
\n
A report formatter plugin gives you the ability to export enqueuer reports the way you want.\nRun $ nqr -f [formatter-name] to list available report formatters:
Consider looking at the example of configuration file to see it in use.\nThis one, for instance, generates xUnit like reports from enqueuer's output.
\n
plugin installation
\n
In order to enqueuer get awareness that you want to use a plugin, you have to tell it, right?\nYou can tell enqueuer to use a plugin in three different ways: using it as a command line argument, through the configuration file or letting enqueuer finding it in a default location.
\n
command line
\n
Tell enqueuer to use your plugin through command line this way $ nqr -l <plugin-folder> -l <another-plugin-folder>.\nWhere plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
configuration file
\n
Tell enqueuer to use your plugin through configuration file this way:
Where plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
implicitly
\n
When enqueuer runs, it looks for modules in its same installation directory or in .nqr folder in the home directory, a.k.a. ~/ folder in linux distributions.\nTherefore, if you run:
You'll see that the enqueuer-plugin-amqp plugin will be loaded.\nEvery enqueuer compatible module gets implicitly loaded.\nIn order to be enqueuer compatible, a module has to have an entryPoint exported function in its main file and, in its package.json file, it has to have either 'enqueuer' or 'nqr' as keywords.
\n
Stacker
\n
Looking for a really really good looking an human error proof solution way of writing these requisition files? \nConsider taking a look at stacker: open source, cross-platform, multi protocol client testing tool.\nThe official enqueuer's best friend forever. Do amazing things and change the world with enqueuer’s GUI!\nWith them, you create, manage and run requisitions and and see their results in a really nice way.\nSee this amazing beauty with your own eyes to get an idea of how it works:
\n
\n\n
Open source
\n
We (by 'we' we mean enqueuer's maintainers not the human race, unfortunately) are very opened to any kind of contributions in general.\nAs long as they make sense and add value to the product, you're free to go.\nWe mean it, do it. Even if it's a typo fix in this README file. Go ahead.\nIf you like it but don't want to waste time creating a pull request, no problem either.\nCreate an issue, or, even easier, give it a github star. It's cheap and it doesn't hurt anyone.\nYou know what? Just head up to enqueuer's github repo and keep staring at its repo.\nIt may help somehow.
In order to contribute with some code, you have to follow a few steps.\nFirst of all, get the code:
\n
$ git clone git@github.com:enqueuer-land/enqueuer.git\n$ cd enqueuer\n
\n
Get its dependencies installed:
\n
$ npm install\n
\n
Build it:
\n
$ npm run build\n
\n
Go for it. Make the changes you want.\nAfter everything is done:
\n
$ npm run all\n
\n
Commit it:
\n
$ npm run commit\n
\n
Push it:
\n
$ git push\n
\n
feedback
\n
We'd love to get your feedback!\nIf you have any comments, suggestions, etc. you can reach us here.
\n
\n\n
\n
\n\n\n\n
\n
\n\n \n
\n \n\n
\n\n \n\n\n\n\n
\n \n \n You can’t perform that action at this time.\n
\n\n\n \n \n \n \n \n \n \n
\n \n You signed in with another tab or window. Reload to refresh your session.\n You signed out in another tab or window. Reload to refresh your session.\n
\n Over 40 million developers use GitHub together\n to host and review code, project manage, and build software together\n across more than 100 million projects.\n
Now go ahead and try hitting it using the browser.\nTip: remove timeout values and check what happens.\nI told you it was simple.\nNow, let's say you want to mix different protocols to test a bit more complex flow.\nHow about publishing an amqp message and making sure that, once a service consumes that message an endpoint of your is hit?\nIn order to achieve that, we have to make use of a plugin, given that amqp support is provided by a plugin.\nIn this scenario, we're talking about the amqp plugin.\nOnce we get this plugin installed we are able to create and run files like this:
Now go nuts!\nIt's all yours. Have fun.\nIf you want more examples about http, consider looking at this test.\nCheck this out, you'll find countless examples.\nCertainly one is what you need.
\n
if you need more
\n
$ nqr -h\nUsage: nqr [options] <test-file> [other-test-files...]\n\nTake a look at the full documentation: https://enqueuer.com\n\nOptions:\n -v, --version output the version number\n -b, --verbosity <level> set verbosity (default: \"warn\")\n -c, --config-file <path> set configurationFile\n -e, --parsers-list [parser] list available object parsers\n -f, --formatters-description [formatter] describe report formatters\n -o, --stdout-requisition-output add stdout as requisition output\n -m, --max-report-level-print <level> set max report level print\n -p, --protocols-description [protocol] describe protocols\n -t, --tests-list [expectedField] list available tests assertions\n -u, --loaded-modules-list list loaded modules\n -i, --show-passing-tests show passing tests\n -s, --store [store] add variables values to this session (default: [])\n -l, --add-plugin [plugin] add plugin (default: [])\n -a, --add-file <file> add file to be tested (default: [])\n -A, --add-file-and-ignore-others <file> add file to be tested and ignore others (default: [])\n -h, --help output usage information\n\nExamples:\n $ nqr --config-file config-file.yml --verbosity error --store key=value\n $ enqueuer -c config-file.yml test-file.yml --add-file another-test-file.yml -b info\n $ enqueuer test-file.yml --store someKey=true --store someOtherKey=false\n $ nqr --protocols-description -s key=value\n $ nqr -t expect\n $ nqr -l my-enqueuer-plugin-name -p plugin-protocol\n $ nqr -p http\n $ nqr --formatters-description json\n \nContributing:\n https://github.com/enqueuer-land/enqueuer\n
\n\n
Components
\n
In order to accomplish more than just hitting enqueuer's repo or doing a quick self http hit, there are a few things that you'll probably need to know.\nDon't worry, it's not too much and, as mentioned earlier, there is a lot of examples here, just in case.\nThere are only three important component concepts: requisitions, publishers and subscriptions.\nThey work along with each other and are responsible for the full behavior of enqueuer.
\n
requisition
\n
Test scenario description. It tells what, when, and how test your applications and services.\nPicture it as if it was a collection of publishers, subscriptions and other requisitions.\nIt helps because this is exactly what it is.\nAs the others components, it has some attributes. All of them are optionals. And it supports multi-level test scenarios out of the box. Yeap, go as recursive as you want.\nEvery test file is a requisition.\nYou don't know some of these attributes values yet? Don't worry, just put a variable there and let enqueuer replace it with the value you set later.\nVariable replacements are available through the entire requisition.
\n
requisition attributes
\n
These are the requisition attributes:
\n
name \nDescribes what the requisition is suppose to do.\nDefaults to requisition index.
\n
name: requisition action\n
\n
timeout \nDefaults to 5000.\nSets in milliseconds how long the requisition waits to expire.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
delay \nDefaults to 0. Sets in milliseconds how long the test waits before starting. Check this to get the full idea.
\n
delay: 0\n
\n
iterations \nDefaults to 1. Sets how many times this test will be executed. Check this and this to get the full idea.
\n
iterations: 3\n
\n
ignore \nDefaults to false. Tells to enqueuer that this requisitions should be skipped. Check this to see it working.
\n
ignore: true\n
\n
parallel \nDefaults to false. Immediate children requisitions should be executed in parallel mode.\nTake a look at this to see it working.
\n
parallel: true\n
\n
import \nAllows requisition to be dynamically defined, be it by loading an external file or creating dynamically by other requisitions. Want to reuse the same requisition multiple times? This is you you need.\nTake a look at this to behold this feature.
\n
import: path/to/another/requisition/file\n
\n
publishers \nList of publishers. They're executed simultaneously, therefore, the order is irrelevant.
\n
publishers:\n- name: some publisher name\n type: http\n- type: tcp\n
\n
subscriptions \nList of subscriptions. They're executed simultaneously, therefore, the order is irrelevant.
\n
subscriptions:\n- name: some subscription name\n type: udp\n- name: another subscription name\n type: file\n
\n
requisitions \nA list of child scenarios. List of requisitions.\nBy default, they're executed sequentially, therefore, the order is relevant.\nUnless the parallel attribute is set to true, what makes them get executed simultaneously,\nCheck this example, it may help.
\n
requisitions:\n- name: some requisition name\n iterations: 2\n- name: another requisition name\n delay: 200\n
\n
events
\n
Available events are described here. A this object is available to access and change requisition attributes.
A publisher action is triggered by enqueuer itself. It acts whereas a subscriptionreacts.\nIt publishes something, it writes, it enqueues, hits and endpoint... These kinds of actions.\nIt's worth noting that it always creates a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if the message got published.
\n
publisher attributes
\n
Every publisher has its own properties, depending on its protocol and implementation.\nThe built-in http publisher implementation, for instance, demands a url, a method, and a payload, if the method is not a GET.\nOn the other hand, the built-in tcp publisher implementation requires a serverAddress and a port.\nThese are the publisher attributes:
\n
name \nDefaults to publisher index.\nDescribes what the publisher is supposed to do.
\n
name: publisher action\n
\n
type \nMandatory. Key tag to identify which publisher will be instantiated
\n
type: http\n
\n
payload \nSince a publisher usually publishes something, it's very likely you have to set a value here.\nThe message itself that will be send through this protocol. Be it a string, a number, a boolean value or even whole objects.
\n
payload: value\n
\n
ignore \nDefaults to false. Tells to enqueuer that this publisher should be skipped. Check this to see it working.
\n
ignore: true\n
\n
events
\n
Available events are described here. A this object is available to access and change publisher attributes.\nDepending on the protocol and its implementation, such as http and tcp, there may exist special events, such as onMessageReceived event and a special object given message.\nOn the other hand, an asynchronous protocol, like: udp and amqp, usually do not provide it.
A subscription is an \"under demand\" event. It reacts whereas a publisheracts.\nIt consumes something, it reads, it dequeues, gets hit... These kinds of actions.\nThis means that it is not triggered by enqueuer itself.\nRather than that, enqueuer waits on an external event to be triggered and then it asserts against the message that was passed to the subscription.\nIt's worth noting that it always receives a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if a message got received.
\n
subscription attributes
\n
Every subscription has its own properties, depending on its protocol and implementation.\nThe built-in http subscription implementation, for instance, demands an endpoint, a method, and a port, if the method is not a GET.\nOn the other hand, the built-in tcp subscription implementation requires only a port.
\n
These are the subscription attributes:
\n
name \nDefaults to subscription index.\nDescribes what the subscription is supposed to do.
\n
name: subscription action\n
\n
type \nMandatory. Key tag to identify which subscription will be instantiated
\n
type: http\n
\n
avoid \nIdentifies whether or not this subscription should not receive any message. Defaults to false.\nIf set and a message is received a failing test will be generated.\nTake a look at this to see it working.\nOn the other hand, when it's false and no message is received in a given timeout. The subscription is valid.
\n
avoid: false\n
\n
timeout \nSets in milliseconds how long the subscription waits to expire. Defaults to 3000.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
ignore \nDefaults to false. Tells to enqueuer that this subscription should be skipped. Check this to see it working.
\n
ignore: true \n
\n
events
\n
Available events are described here. A this object is available to access and change subscription attributes.
Events are hook methods executed by enqueuer when an action occurs on publishers, subscriptions or requisitions.\nThis is where you'll write your tests. In its assertions field.\nThere will be a variable called this and, depending on the event's owner, it has an alias publisher, subscription or requisition.\nYou're free to explore them however you want, even doing things like this:
By default, there are three hook events available:
\n
onInit \nAvailable in requisitions, publishers and subscriptions. It gets executed as soon as the component is initialized.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
onFinish \nAvailable in requisitions, publishers and subscriptions. It gets executed when the component is about to finish.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
custom\nDepending on the protocol implementation/library/author's mood, the publisher/subscription may have additional hooks.\nSuch as onError, onResponseReceived, onFileNotFound and onRedirect...\nHttp-proxy subscription test file is an excellent example, check it out.
\n
fields
\n
Every hook object has 3 properties:
\n
script \nJavascript code snippet executed when the event is triggered.\nYeah, I mean it. See it it by yourself.\nBut be careful, with great power comes great responsibility.
\n
store \nData to be persisted across requisitions.
\n
assertions \nArray of assertions.\nRun $ nqr -t to see available ones.\nConsider looking at this test example.\nOf course, just like almost everything else in enqueuer world, you can extend this available list using some plugin.\nYou can check them out or even write your own.
Now that you know what are requisitions, publishers, subscriptions and events. How about seeing how they interact with each other in a fancier way?
\n
\n\n
Configuration File
\n
To save yourself some time, a configuration file may be used.\nConfiguration files tell enqueuer which tests will be executed, log-level, and which output test report files should be generated.\nThis file tells how enqueuer should be executed.\nTo run enqueuer with the configuration:
files \nRequisition file names or glob. Enqueuer runs every file that matches an element value.
\n
files:\n- 1.yml\n- 2.yml\n- *.json\n
\n
parallel \nDefaults to false. Requisition files should be executed in parallel mode. The requisition file itself is still sequential, but the files are executes in parallel.
\n
parallel: true\n
\n
log-level \nDefaults to warning. Defines how information are logged in the console. Accepted values are: trace; debug; info; warning (default); error; and fatal.
\n
log-level: trace\n
\n
max-report-level-print \nDefaults to 1. The deepest level of report to be printed to the console.
outputs \nOnce enqueuer runs every execution, it compiles a summary and sends it to every publisher listed in output.\nAn important thing to note is that every available report publisher is available here.\nYes, it means that you are able to send this report through http, tcp, etc. or through a plugin one or a custom one.\nYou can run $ nqr -p to check available report publishers installed.\nAnother important thing to note is the format value. By default a json summary is generated, but you can change it to whatever format you would like, such as: Xunit, html\nYou can run $ nqr -f to check available installed formats or even write your own
store \nValues defined here use the 'key: value' pattern and are available to every test scenario throughout the entire execution
\n
store:\n variableKey: \"my value\" # Defines 'variableKey' key and its value 'my value'. \n \n 'separated key': 6\n \n object: # You can even define whole objects here:\n first: first value\n second:\n nested: thing\n
\n
example
\n
Here's a complete example of a configuration file.
\n\n
Variables
\n
Providing power and flexibility, enqueuer allows you to use variables placeholder replacement.\nThat's why there is a store field and you'll see a lot of << and {{ being used in the examples files.\nIt works as simple as this:
\n
name: my name is <<variableKey>>\n
\n
Every time enqueuer sees these kind of notations, it searches in its store for a key/value pair like:
\n
variableKey: `enqueuer`\n
\n
Then, when enqueuer parses the original map, it gets translated to this:
\n
name: my name is enqueuer\n
\n
By default, every ENV_VAR set is loaded automatically to the store. Check this example.
\n
set a variable
\n
There are a few ways to set a value in the store.
\n
configuration file
\n
Configuration file store object. Set it as you wish, as you can see here
\n
command line
\n
A command line argument using the key=value format. This way:
\n
$ nqr --store key=value -s anotherVariable=true\n
\n
event
\n
Dynamically set it through any event.\nBe it in its script field or straight through its store field.\nBoth ways work:
The easiest one is to type <<variableKey>> or {{variableKey}} where you want it to be replaced in a test file, as you can see here
\n
js code snippet
\n
Using the store object. It's attributes are the keys and their values are their respective values.\nTherefore, you're free to use store.variableKey, console.log(store.variableKey); or console.log(2 * store['separated key']); and get them.\nLike this one.
It get's event better.\nDue its fantastic plugin architecture design, you can extend its default modules and use any of these plugins or event write your own to parse however you want.\nThe built-in modules for object parsers are: json, yml, csv and file.\nRun $ nqr -e to see available ones.
You're probably aware by now but it doesn't hurt do emphasize it: enqueuer provides an amazingly powerful plugin extensible architecture.\nIt has several plugins available, but if none of them pleases you, you're free to create your own.\nAlbeit you don't have to share the one you created, we encourage you to do so. Then go ahead and publish yours to npm and add it to our plugins list.
\n
plugin types
\n
So far, you're able to extend enqueuer default behavior in four ways. Using a protocol plugin, an object parser plugin, an asserter plugin and using a report formatter plugin.
\n
protocol
\n
A protocol plugin enables you to use a different publisher/subscription types.\nRun $ nqr -p [protocol-name] to get the full available list:
Each one listed above has a respective example in the examples folder.\nThis one, for instance, provides support for amqp protocol, so you can create this publisher and subscription:
An object parser plugin enables you to read and parse files as you wish.\nThis test example demonstrates how to use it,\nRun $ nqr -e [object-parser-name] to check available ones:
\n
parsers: \n- yml, yaml\n- json\n- file\n- csv\n
\n
This one, for example, provides the ability to read xml files and inject their values like this:
\n
xmlContent: <<xml://path/to/xml/file.xml>>\n
\n
asserter
\n
An asserter plugin provides you a nicely way to use different assertions than these built-in ones.
Run $ nqr -t to get the full available list.\nConsider looking at this test example.
\n
report formatter
\n
A report formatter plugin gives you the ability to export enqueuer reports the way you want.\nRun $ nqr -f [formatter-name] to list available report formatters:
Consider looking at the example of configuration file to see it in use.\nThis one, for instance, generates xUnit like reports from enqueuer's output.
\n
plugin installation
\n
In order to enqueuer get awareness that you want to use a plugin, you have to tell it, right?\nYou can tell enqueuer to use a plugin in three different ways: using it as a command line argument, through the configuration file or letting enqueuer finding it in a default location.
\n
command line
\n
Tell enqueuer to use your plugin through command line this way $ nqr -l <plugin-folder> -l <another-plugin-folder>.\nWhere plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
configuration file
\n
Tell enqueuer to use your plugin through configuration file this way:
Where plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
implicitly
\n
When enqueuer runs, it looks for modules in its same installation directory or in .nqr folder in the home directory, a.k.a. ~/ folder in linux distributions.\nTherefore, if you run:
You'll see that the enqueuer-plugin-amqp plugin will be loaded.\nEvery enqueuer compatible module gets implicitly loaded.\nIn order to be enqueuer compatible, a module has to have an entryPoint exported function in its main file and, in its package.json file, it has to have either 'enqueuer' or 'nqr' as keywords.
\n
Stacker
\n
Looking for a really really good looking an human error proof solution way of writing these requisition files? \nConsider taking a look at stacker: open source, cross-platform, multi protocol client testing tool.\nThe official enqueuer's best friend forever. Do amazing things and change the world with enqueuer’s GUI!\nWith them, you create, manage and run requisitions and and see their results in a really nice way.\nSee this amazing beauty with your own eyes to get an idea of how it works:
\n
\n\n
Open source
\n
We (by 'we' we mean enqueuer's maintainers not the human race, unfortunately) are very opened to any kind of contributions in general.\nAs long as they make sense and add value to the product, you're free to go.\nWe mean it, do it. Even if it's a typo fix in this README file. Go ahead.\nIf you like it but don't want to waste time creating a pull request, no problem either.\nCreate an issue, or, even easier, give it a github star. It's cheap and it doesn't hurt anyone.\nYou know what? Just head up to enqueuer's github repo and keep staring at its repo.\nIt may help somehow.
In order to contribute with some code, you have to follow a few steps.\nFirst of all, get the code:
\n
$ git clone git@github.com:enqueuer-land/enqueuer.git\n$ cd enqueuer\n
\n
Get its dependencies installed:
\n
$ npm install\n
\n
Build it:
\n
$ npm run build\n
\n
Go for it. Make the changes you want.\nAfter everything is done:
\n
$ npm run all\n
\n
Commit it:
\n
$ npm run commit\n
\n
Push it:
\n
$ git push\n
\n
feedback
\n
We'd love to get your feedback!\nIf you have any comments, suggestions, etc. you can reach us here.
\n
\n\n
\n
\n\n\n\n\n
\n
\n\n \n
\n \n\n
\n\n \n\n\n\n\n
\n \n \n You can’t perform that action at this time.\n
\n\n\n \n \n \n \n \n \n \n
\n \n You signed in with another tab or window. Reload to refresh your session.\n You signed out in another tab or window. Reload to refresh your session.\n
Now go ahead and try hitting it using the browser.\nTip: remove timeout values and check what happens.\nI told you it was simple.\nNow, let's say you want to mix different protocols to test a bit more complex flow.\nHow about publishing an amqp message and making sure that, once a service consumes that message an endpoint of your is hit?\nIn order to achieve that, we have to make use of a plugin, given that amqp support is provided by a plugin.\nIn this scenario, we're talking about the amqp plugin.\nOnce we get this plugin installed we are able to create and run files like this:
Now go nuts!\nIt's all yours. Have fun.\nIf you want more examples about http, consider looking at this test.\nCheck this out, you'll find countless examples.\nCertainly one is what you need.
\n
if you need more
\n
$ nqr -h\nUsage: nqr [options] <test-file> [other-test-files...]\n\nTake a look at the full documentation: https://enqueuer.com\n\nOptions:\n -v, --version output the version number\n -b, --verbosity <level> set verbosity (default: \"warn\")\n -c, --config-file <path> set configurationFile\n -e, --parsers-list [parser] list available object parsers\n -f, --formatters-description [formatter] describe report formatters\n -o, --stdout-requisition-output add stdout as requisition output\n -m, --max-report-level-print <level> set max report level print\n -p, --protocols-description [protocol] describe protocols\n -t, --tests-list [expectedField] list available tests assertions\n -u, --loaded-modules-list list loaded modules\n -i, --show-passing-tests show passing tests\n -s, --store [store] add variables values to this session (default: [])\n -l, --add-plugin [plugin] add plugin (default: [])\n -a, --add-file <file> add file to be tested (default: [])\n -A, --add-file-and-ignore-others <file> add file to be tested and ignore others (default: [])\n -h, --help output usage information\n\nExamples:\n $ nqr --config-file config-file.yml --verbosity error --store key=value\n $ enqueuer -c config-file.yml test-file.yml --add-file another-test-file.yml -b info\n $ enqueuer test-file.yml --store someKey=true --store someOtherKey=false\n $ nqr --protocols-description -s key=value\n $ nqr -t expect\n $ nqr -l my-enqueuer-plugin-name -p plugin-protocol\n $ nqr -p http\n $ nqr --formatters-description json\n
\n\n
Components
\n
In order to accomplish more than just hitting enqueuer's repo or doing a quick self http hit, there are a few things that you'll probably need to know.\nDon't worry, it's not too much and, as mentioned earlier, there is a lot of examples here, just in case.\nThere are only three important component concepts: requisitions, publishers and subscriptions.\nThey work along with each other and are responsible for the full behavior of enqueuer.
\n
requisition
\n
Test scenario description. It tells what, when, and how test your applications and services.\nPicture it as if it was a collection of publishers, subscriptions and other requisitions.\nIt helps because this is exactly what it is.\nAs the others components, it has some attributes. All of them are optionals. And it supports multi-level test scenarios out of the box. Yeap, go as recursive as you want.\nEvery test file is a requisition.\nYou don't know some of these attributes values yet? Don't worry, just put a variable there and let enqueuer replace it with the value you set later.\nVariable replacements are available through the entire requisition.
\n
requisition attributes
\n
These are the requisition attributes:
\n
name \nDescribes what the requisition is suppose to do.\nDefaults to requisition index.
\n
name: requisition action\n
\n
timeout \nDefaults to 5000.\nSets in milliseconds how long the requisition waits to expire.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
delay \nDefaults to 0. Sets in milliseconds how long the test waits before starting. Check this to get the full idea.
\n
delay: 0\n
\n
iterations \nDefaults to 1. Sets how many times this test will be executed. Check this and this to get the full idea.
\n
iterations: 3\n
\n
ignore \nDefaults to false. Tells to enqueuer that this requisitions should be skipped. Check this to see it working.
\n
ignore: true\n
\n
parallel \nDefaults to false. Immediate children requisitions should be executed in parallel mode.\nTake a look at this to see it working.
\n
parallel: true\n
\n
import \nAllows requisition to be dynamically defined, be it by loading an external file or creating dynamically by other requisitions. Want to reuse the same requisition multiple times? This is you you need.\nTake a look at this to behold this feature.
\n
import: path/to/another/requisition/file\n
\n
publishers \nList of publishers. They're executed simultaneously, therefore, the order is irrelevant.
\n
publishers:\n- name: some publisher name\n type: http\n- type: tcp\n
\n
subscriptions \nList of subscriptions. They're executed simultaneously, therefore, the order is irrelevant.
\n
subscriptions:\n- name: some subscription name\n type: udp\n- name: another subscription name\n type: file\n
\n
requisitions \nA list of child scenarios. List of requisitions.\nBy default, they're executed sequentially, therefore, the order is relevant.\nUnless the parallel attribute is set to true, what makes them get executed simultaneously,\nCheck this example, it may help.
\n
requisitions:\n- name: some requisition name\n iterations: 2\n- name: another requisition name\n delay: 200\n
\n
events
\n
Available events are described here. A this object is available to access and change requisition attributes.
A publisher action is triggered by enqueuer itself. It acts whereas a subscriptionreacts.\nIt publishes something, it writes, it enqueues, hits and endpoint... These kinds of actions.\nIt's worth noting that it always creates a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if the message got published.
\n
publisher attributes
\n
Every publisher has its own properties, depending on its protocol and implementation.\nThe built-in http publisher implementation, for instance, demands a url, a method, and a payload, if the method is not a GET.\nOn the other hand, the built-in tcp publisher implementation requires a serverAddress and a port.\nThese are the publisher attributes:
\n
name \nDefaults to publisher index.\nDescribes what the publisher is supposed to do.
\n
name: publisher action\n
\n
type \nMandatory. Key tag to identify which publisher will be instantiated
\n
type: http\n
\n
payload \nSince a publisher usually publishes something, it's very likely you have to set a value here.\nThe message itself that will be send through this protocol. Be it a string, a number, a boolean value or even whole objects.
\n
payload: value\n
\n
ignore \nDefaults to false. Tells to enqueuer that this publisher should be skipped. Check this to see it working.
\n
ignore: true\n
\n
events
\n
Available events are described here. A this object is available to access and change publisher attributes.\nDepending on the protocol and its implementation, such as http and tcp, there may exist special events, such as onMessageReceived event and a special object given message.\nOn the other hand, an asynchronous protocol, like: udp and amqp, usually do not provide it.
A subscription is an \"under demand\" event. It reacts whereas a publisheracts.\nIt consumes something, it reads, it dequeues, gets hit... These kinds of actions.\nThis means that it is not triggered by enqueuer itself.\nRather than that, enqueuer waits on an external event to be triggered and then it asserts against the message that was passed to the subscription.\nIt's worth noting that it always receives a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if a message got received.
\n
subscription attributes
\n
Every subscription has its own properties, depending on its protocol and implementation.\nThe built-in http subscription implementation, for instance, demands an endpoint, a method, and a port, if the method is not a GET.\nOn the other hand, the built-in tcp subscription implementation requires only a port.
\n
These are the subscription attributes:
\n
name \nDefaults to subscription index.\nDescribes what the subscription is supposed to do.
\n
name: subscription action\n
\n
type \nMandatory. Key tag to identify which subscription will be instantiated
\n
type: http\n
\n
avoid \nIdentifies whether or not this subscription should not receive any message. Defaults to false.\nIf set and a message is received a failing test will be generated.\nTake a look at this to see it working.\nOn the other hand, when it's false and no message is received in a given timeout. The subscription is valid.
\n
avoid: false\n
\n
timeout \nSets in milliseconds how long the subscription waits to expire. Defaults to 3000.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
ignore \nDefaults to false. Tells to enqueuer that this subscription should be skipped. Check this to see it working.
\n
ignore: true \n
\n
events
\n
Available events are described here. A this object is available to access and change subscription attributes.
Events are hook methods executed by enqueuer when an action occurs on publishers, subscriptions or requisitions.\nThis is where you'll write your tests. In its assertions field.\nThere will be a variable called this and, depending on the event's owner, it has an alias publisher, subscription or requisition.\nYou're free to explore them however you want, even doing things like this:
By default, there are three hook events available:
\n
onInit \nAvailable in requisitions, publishers and subscriptions. It gets executed as soon as the component is initialized.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
onFinish \nAvailable in requisitions, publishers and subscriptions. It gets executed when the component is about to finish.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
custom\nDepending on the protocol implementation/library/author's mood, the publisher/subscription may have additional hooks.\nSuch as onError, onResponseReceived, onFileNotFound and onRedirect...\nHttp-proxy subscription test file is an excellent example, check it out.
\n
fields
\n
Every hook object has 3 properties:
\n
script \nJavascript code snippet executed when the event is triggered.\nYeah, I mean it. See it it by yourself.\nBut be careful, with great power comes great responsibility.
\n
store \nData to be persisted across requisitions.
\n
assertions \nArray of assertions.\nRun $ nqr -t to see available ones.\nConsider looking at this test example.\nOf course, just like almost everything else in enqueuer world, you can extend this available list using some plugin.\nYou can check them out or even write your own.
Now that you know what are requisitions, publishers, subscriptions and events. How about seeing how they interact with each other in a fancier way?
\n
\n\n
Configuration File
\n
To save yourself some time, a configuration file may be used.\nConfiguration files tell enqueuer which tests will be executed, log-level, and which output test report files should be generated.\nThis file tells how enqueuer should be executed.\nTo run enqueuer with the configuration:
files \nRequisition file names or glob. Enqueuer runs every file that matches an element value.
\n
files:\n- 1.yml\n- 2.yml\n- *.json\n
\n
parallel \nDefaults to false. Requisition files should be executed in parallel mode. The requisition file itself is still sequential, but the files are executes in parallel.
\n
parallel: true\n
\n
log-level \nDefaults to warning. Defines how information are logged in the console. Accepted values are: trace; debug; info; warning (default); error; and fatal.
\n
log-level: trace\n
\n
max-report-level-print \nDefaults to 1. The deepest level of report to be printed to the console.
outputs \nOnce enqueuer runs every execution, it compiles a summary and sends it to every publisher listed in output.\nAn important thing to note is that every available report publisher is available here.\nYes, it means that you are able to send this report through http, tcp, etc. or through a plugin one or a custom one.\nYou can run $ nqr -p to check available report publishers installed.\nAnother important thing to note is the format value. By default a json summary is generated, but you can change it to whatever format you would like, such as: Xunit, html\nYou can run $ nqr -f to check available installed formats or even write your own
store \nValues defined here use the 'key: value' pattern and are available to every test scenario throughout the entire execution
\n
store:\n variableKey: \"my value\" # Defines 'variableKey' key and its value 'my value'. \n \n 'separated key': 6\n \n object: # You can even define whole objects here:\n first: first value\n second:\n nested: thing\n
\n
example
\n
Here's a complete example of a configuration file.
\n\n
Variables
\n
Providing power and flexibility, enqueuer allows you to use variables placeholder replacement.\nThat's why there is a store field and you'll see a lot of << and {{ being used in the examples files.\nIt works as simple as this:
\n
name: my name is <<variableKey>>\n
\n
Every time enqueuer sees these kind of notations, it searches in its store for a key/value pair like:
\n
variableKey: `enqueuer`\n
\n
Then, when enqueuer parses the original map, it gets translated to this:
\n
name: my name is enqueuer\n
\n
By default, every ENV_VAR set is loaded automatically to the store. Check this example.
\n
set a variable
\n
There are a few ways to set a value in the store.
\n
configuration file
\n
Configuration file store object. Set it as you wish, as you can see here
\n
command line
\n
A command line argument using the key=value format. This way:
\n
$ nqr --store key=value -s anotherVariable=true\n
\n
event
\n
Dynamically set it through any event.\nBe it in its script field or straight through its store field.\nBoth ways work:
The easiest one is to type <<variableKey>> or {{variableKey}} where you want it to be replaced in a test file, as you can see here
\n
js code snippet
\n
Using the store object. It's attributes are the keys and their values are their respective values.\nTherefore, you're free to use store.variableKey, console.log(store.variableKey); or console.log(2 * store['separated key']); and get them.\nLike this one.
It get's event better.\nDue its fantastic plugin architecture design, you can extend its default modules and use any of these plugins or event write your own to parse however you want.\nThe built-in modules for object parsers are: json, yml, csv and file.\nRun $ nqr -e to see available ones.
You're probably aware by now but it doesn't hurt do emphasize it: enqueuer provides an amazingly powerful plugin extensible architecture.\nIt has several plugins available, but if none of them pleases you, you're free to create your own.\nAlbeit you don't have to share the one you created, we encourage you to do so. Then go ahead and publish yours to npm and add it to our plugins list.
\n
plugin types
\n
So far, you're able to extend enqueuer default behavior in four ways. Using a protocol plugin, an object parser plugin, an asserter plugin and using a report formatter plugin.
\n
protocol
\n
A protocol plugin enables you to use a different publisher/subscription types.\nRun $ nqr -p [protocol-name] to get the full available list:
Each one listed above has a respective example in the examples folder.\nThis one, for instance, provides support for amqp protocol, so you can create this publisher and subscription:
An object parser plugin enables you to read and parse files as you wish.\nThis test example demonstrates how to use it,\nRun $ nqr -e [object-parser-name] to check available ones:
\n
parsers: \n- yml, yaml\n- json\n- file\n- csv\n
\n
This one, for example, provides the ability to read xml files and inject their values like this:
\n
xmlContent: <<xml://path/to/xml/file.xml>>\n
\n
asserter
\n
An asserter plugin provides you a nicely way to use different assertions than these built-in ones.
Run $ nqr -t to get the full available list.\nConsider looking at this test example.
\n
report formatter
\n
A report formatter plugin gives you the ability to export enqueuer reports the way you want.\nRun $ nqr -f [formatter-name] to list available report formatters:
Consider looking at the example of configuration file to see it in use.\nThis one, for instance, generates xUnit like reports from enqueuer's output.
\n
plugin installation
\n
In order to enqueuer get awareness that you want to use a plugin, you have to tell it, right?\nYou can tell enqueuer to use a plugin in three different ways: using it as a command line argument, through the configuration file or letting enqueuer finding it in a default location.
\n
command line
\n
Tell enqueuer to use your plugin through command line this way $ nqr -l <plugin-folder> -l <another-plugin-folder>.\nWhere plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
configuration file
\n
Tell enqueuer to use your plugin through configuration file this way:
Where plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
implicitly
\n
When enqueuer runs, it looks for modules in its same installation directory or in .nqr folder in the home directory, a.k.a. ~/ folder in linux distributions.\nTherefore, if you run:
You'll see that the enqueuer-plugin-amqp plugin will be loaded.\nEvery enqueuer compatible module gets implicitly loaded.\nIn order to be enqueuer compatible, a module has to have an entryPoint exported function in its main file and, in its package.json file, it has to have either 'enqueuer' or 'nqr' as keywords.
\n
Stacker
\n
Looking for a really really good looking an human error proof solution way of writing these requisition files? \nConsider taking a look at stacker: open source, cross-platform, multi protocol client testing tool.\nThe official enqueuer's best friend forever. Do amazing things and change the world with enqueuer’s GUI!\nWith them, you create, manage and run requisitions and and see their results in a really nice way.\nSee this amazing beauty with your own eyes to get an idea of how it works:
\n
\n\n
Open source
\n
We (by 'we' we mean enqueuer's maintainers not the human race, unfortunately) are very opened to any kind of contributions in general.\nAs long as they make sense and add value to the product, you're free to go.\nWe mean it, do it. Even if it's a typo fix in this README file. Go ahead.\nIf you like it but don't want to waste time creating a pull request, no problem either.\nCreate an issue, or, even easier, give it a github star. It's cheap and it doesn't hurt anyone.\nYou know what? Just head up to enqueuer's github repo and keep staring at its repo.\nIt may help somehow.
In order to contribute with some code, you have to follow a few steps.\nFirst of all, get the code:
\n
$ git clone git@github.com:enqueuer-land/enqueuer.git\n$ cd enqueuer\n
\n
Get its dependencies installed:
\n
$ npm install\n
\n
Build it:
\n
$ npm run build\n
\n
Go for it. Make the changes you want.\nAfter everything is done:
\n
$ npm run all\n
\n
Commit it:
\n
$ npm run commit\n
\n
Push it:
\n
$ git push\n
\n
feedback
\n
We'd love to get your feedback!\nIf you have any comments, suggestions, etc. you can reach us here.
\n
\n\n
\n
\n\n\n\n
\n
\n\n \n
\n \n\n
\n\n \n\n\n\n\n
\n \n \n You can’t perform that action at this time.\n
\n\n\n \n \n \n \n \n \n \n
\n \n You signed in with another tab or window. Reload to refresh your session.\n You signed out in another tab or window. Reload to refresh your session.\n
\n Over 40 million developers use GitHub together\n to host and review code, project manage, and build software together\n across more than 100 million projects.\n
Now go ahead and try hitting it using the browser.\nTip: remove timeout values and check what happens.\nI told you it was simple.\nNow, let's say you want to mix different protocols to test a bit more complex flow.\nHow about publishing an amqp message and making sure that, once a service consumes that message an endpoint of your is hit?\nIn order to achieve that, we have to make use of a plugin, given that amqp support is provided by a plugin.\nIn this scenario, we're talking about the amqp plugin.\nOnce we get this plugin installed we are able to create and run files like this:
Now go nuts!\nIt's all yours. Have fun.\nIf you want more examples about http, consider looking at this test.\nCheck this out, you'll find countless examples.\nCertainly one is what you need.
\n
if you need more
\n
$ nqr -h\nUsage: nqr [options] <test-file> [other-test-files...]\n\nTake a look at the full documentation: https://enqueuer.com\n\nOptions:\n -v, --version output the version number\n -b, --verbosity <level> set verbosity (default: \"warn\")\n -c, --config-file <path> set configurationFile\n -e, --parsers-list [parser] list available object parsers\n -f, --formatters-description [formatter] describe report formatters\n -o, --stdout-requisition-output add stdout as requisition output\n -m, --max-report-level-print <level> set max report level print\n -p, --protocols-description [protocol] describe protocols\n -t, --tests-list [expectedField] list available tests assertions\n -u, --loaded-modules-list list loaded modules\n -i, --show-passing-tests show passing tests\n -s, --store [store] add variables values to this session (default: [])\n -l, --add-plugin [plugin] add plugin (default: [])\n -a, --add-file <file> add file to be tested (default: [])\n -A, --add-file-and-ignore-others <file> add file to be tested and ignore others (default: [])\n -h, --help output usage information\n\nExamples:\n $ nqr --config-file config-file.yml --verbosity error --store key=value\n $ enqueuer -c config-file.yml test-file.yml --add-file another-test-file.yml -b info\n $ enqueuer test-file.yml --store someKey=true --store someOtherKey=false\n $ nqr --protocols-description -s key=value\n $ nqr -t expect\n $ nqr -l my-enqueuer-plugin-name -p plugin-protocol\n $ nqr -p http\n $ nqr --formatters-description json\n \nContributing:\n https://github.com/enqueuer-land/enqueuer\n
\n\n
Components
\n
In order to accomplish more than just hitting enqueuer's repo or doing a quick self http hit, there are a few things that you'll probably need to know.\nDon't worry, it's not too much and, as mentioned earlier, there is a lot of examples here, just in case.\nThere are only three important component concepts: requisitions, publishers and subscriptions.\nThey work along with each other and are responsible for the full behavior of enqueuer.
\n
requisition
\n
Test scenario description. It tells what, when, and how test your applications and services.\nPicture it as if it was a collection of publishers, subscriptions and other requisitions.\nIt helps because this is exactly what it is.\nAs the others components, it has some attributes. All of them are optionals. And it supports multi-level test scenarios out of the box. Yeap, go as recursive as you want.\nEvery test file is a requisition.\nYou don't know some of these attributes values yet? Don't worry, just put a variable there and let enqueuer replace it with the value you set later.\nVariable replacements are available through the entire requisition.
\n
requisition attributes
\n
These are the requisition attributes:
\n
name \nDescribes what the requisition is suppose to do.\nDefaults to requisition index.
\n
name: requisition action\n
\n
timeout \nDefaults to 5000.\nSets in milliseconds how long the requisition waits to expire.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
delay \nDefaults to 0. Sets in milliseconds how long the test waits before starting. Check this to get the full idea.
\n
delay: 0\n
\n
iterations \nDefaults to 1. Sets how many times this test will be executed. Check this and this to get the full idea.
\n
iterations: 3\n
\n
ignore \nDefaults to false. Tells to enqueuer that this requisitions should be skipped. Check this to see it working.
\n
ignore: true\n
\n
parallel \nDefaults to false. Immediate children requisitions should be executed in parallel mode.\nTake a look at this to see it working.
\n
parallel: true\n
\n
import \nAllows requisition to be dynamically defined, be it by loading an external file or creating dynamically by other requisitions. Want to reuse the same requisition multiple times? This is you you need.\nTake a look at this to behold this feature.
\n
import: path/to/another/requisition/file\n
\n
publishers \nList of publishers. They're executed simultaneously, therefore, the order is irrelevant.
\n
publishers:\n- name: some publisher name\n type: http\n- type: tcp\n
\n
subscriptions \nList of subscriptions. They're executed simultaneously, therefore, the order is irrelevant.
\n
subscriptions:\n- name: some subscription name\n type: udp\n- name: another subscription name\n type: file\n
\n
requisitions \nA list of child scenarios. List of requisitions.\nBy default, they're executed sequentially, therefore, the order is relevant.\nUnless the parallel attribute is set to true, what makes them get executed simultaneously,\nCheck this example, it may help.
\n
requisitions:\n- name: some requisition name\n iterations: 2\n- name: another requisition name\n delay: 200\n
\n
events
\n
Available events are described here. A this object is available to access and change requisition attributes.
A publisher action is triggered by enqueuer itself. It acts whereas a subscriptionreacts.\nIt publishes something, it writes, it enqueues, hits and endpoint... These kinds of actions.\nIt's worth noting that it always creates a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if the message got published.
\n
publisher attributes
\n
Every publisher has its own properties, depending on its protocol and implementation.\nThe built-in http publisher implementation, for instance, demands a url, a method, and a payload, if the method is not a GET.\nOn the other hand, the built-in tcp publisher implementation requires a serverAddress and a port.\nThese are the publisher attributes:
\n
name \nDefaults to publisher index.\nDescribes what the publisher is supposed to do.
\n
name: publisher action\n
\n
type \nMandatory. Key tag to identify which publisher will be instantiated
\n
type: http\n
\n
payload \nSince a publisher usually publishes something, it's very likely you have to set a value here.\nThe message itself that will be send through this protocol. Be it a string, a number, a boolean value or even whole objects.
\n
payload: value\n
\n
ignore \nDefaults to false. Tells to enqueuer that this publisher should be skipped. Check this to see it working.
\n
ignore: true\n
\n
events
\n
Available events are described here. A this object is available to access and change publisher attributes.\nDepending on the protocol and its implementation, such as http and tcp, there may exist special events, such as onMessageReceived event and a special object given message.\nOn the other hand, an asynchronous protocol, like: udp and amqp, usually do not provide it.
A subscription is an \"under demand\" event. It reacts whereas a publisheracts.\nIt consumes something, it reads, it dequeues, gets hit... These kinds of actions.\nThis means that it is not triggered by enqueuer itself.\nRather than that, enqueuer waits on an external event to be triggered and then it asserts against the message that was passed to the subscription.\nIt's worth noting that it always receives a message.\nThat's the reason why there's an implicitly created test in onFinish hook verifying if a message got received.
\n
subscription attributes
\n
Every subscription has its own properties, depending on its protocol and implementation.\nThe built-in http subscription implementation, for instance, demands an endpoint, a method, and a port, if the method is not a GET.\nOn the other hand, the built-in tcp subscription implementation requires only a port.
\n
These are the subscription attributes:
\n
name \nDefaults to subscription index.\nDescribes what the subscription is supposed to do.
\n
name: subscription action\n
\n
type \nMandatory. Key tag to identify which subscription will be instantiated
\n
type: http\n
\n
avoid \nIdentifies whether or not this subscription should not receive any message. Defaults to false.\nIf set and a message is received a failing test will be generated.\nTake a look at this to see it working.\nOn the other hand, when it's false and no message is received in a given timeout. The subscription is valid.
\n
avoid: false\n
\n
timeout \nSets in milliseconds how long the subscription waits to expire. Defaults to 3000.\nSet to zero or less than zero to run it endlessly.
\n
timeout: 3000\n
\n
ignore \nDefaults to false. Tells to enqueuer that this subscription should be skipped. Check this to see it working.
\n
ignore: true \n
\n
events
\n
Available events are described here. A this object is available to access and change subscription attributes.
Events are hook methods executed by enqueuer when an action occurs on publishers, subscriptions or requisitions.\nThis is where you'll write your tests. In its assertions field.\nThere will be a variable called this and, depending on the event's owner, it has an alias publisher, subscription or requisition.\nYou're free to explore them however you want, even doing things like this:
By default, there are three hook events available:
\n
onInit \nAvailable in requisitions, publishers and subscriptions. It gets executed as soon as the component is initialized.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
onFinish \nAvailable in requisitions, publishers and subscriptions. It gets executed when the component is about to finish.\nAs available parameter, an elapsedTime variable is given, counting every milliseconds since the instantiation of this component.
\n
custom\nDepending on the protocol implementation/library/author's mood, the publisher/subscription may have additional hooks.\nSuch as onError, onResponseReceived, onFileNotFound and onRedirect...\nHttp-proxy subscription test file is an excellent example, check it out.
\n
fields
\n
Every hook object has 3 properties:
\n
script \nJavascript code snippet executed when the event is triggered.\nYeah, I mean it. See it it by yourself.\nBut be careful, with great power comes great responsibility.
\n
store \nData to be persisted across requisitions.
\n
assertions \nArray of assertions.\nRun $ nqr -t to see available ones.\nConsider looking at this test example.\nOf course, just like almost everything else in enqueuer world, you can extend this available list using some plugin.\nYou can check them out or even write your own.
Now that you know what are requisitions, publishers, subscriptions and events. How about seeing how they interact with each other in a fancier way?
\n
\n\n
Configuration File
\n
To save yourself some time, a configuration file may be used.\nConfiguration files tell enqueuer which tests will be executed, log-level, and which output test report files should be generated.\nThis file tells how enqueuer should be executed.\nTo run enqueuer with the configuration:
files \nRequisition file names or glob. Enqueuer runs every file that matches an element value.
\n
files:\n- 1.yml\n- 2.yml\n- *.json\n
\n
parallel \nDefaults to false. Requisition files should be executed in parallel mode. The requisition file itself is still sequential, but the files are executes in parallel.
\n
parallel: true\n
\n
log-level \nDefaults to warning. Defines how information are logged in the console. Accepted values are: trace; debug; info; warning (default); error; and fatal.
\n
log-level: trace\n
\n
max-report-level-print \nDefaults to 1. The deepest level of report to be printed to the console.
outputs \nOnce enqueuer runs every execution, it compiles a summary and sends it to every publisher listed in output.\nAn important thing to note is that every available report publisher is available here.\nYes, it means that you are able to send this report through http, tcp, etc. or through a plugin one or a custom one.\nYou can run $ nqr -p to check available report publishers installed.\nAnother important thing to note is the format value. By default a json summary is generated, but you can change it to whatever format you would like, such as: Xunit, html\nYou can run $ nqr -f to check available installed formats or even write your own
store \nValues defined here use the 'key: value' pattern and are available to every test scenario throughout the entire execution
\n
store:\n variableKey: \"my value\" # Defines 'variableKey' key and its value 'my value'. \n \n 'separated key': 6\n \n object: # You can even define whole objects here:\n first: first value\n second:\n nested: thing\n
\n
example
\n
Here's a complete example of a configuration file.
\n\n
Variables
\n
Providing power and flexibility, enqueuer allows you to use variables placeholder replacement.\nThat's why there is a store field and you'll see a lot of << and {{ being used in the examples files.\nIt works as simple as this:
\n
name: my name is <<variableKey>>\n
\n
Every time enqueuer sees these kind of notations, it searches in its store for a key/value pair like:
\n
variableKey: `enqueuer`\n
\n
Then, when enqueuer parses the original map, it gets translated to this:
\n
name: my name is enqueuer\n
\n
By default, every ENV_VAR set is loaded automatically to the store. Check this example.
\n
set a variable
\n
There are a few ways to set a value in the store.
\n
configuration file
\n
Configuration file store object. Set it as you wish, as you can see here
\n
command line
\n
A command line argument using the key=value format. This way:
\n
$ nqr --store key=value -s anotherVariable=true\n
\n
event
\n
Dynamically set it through any event.\nBe it in its script field or straight through its store field.\nBoth ways work:
The easiest one is to type <<variableKey>> or {{variableKey}} where you want it to be replaced in a test file, as you can see here
\n
js code snippet
\n
Using the store object. It's attributes are the keys and their values are their respective values.\nTherefore, you're free to use store.variableKey, console.log(store.variableKey); or console.log(2 * store['separated key']); and get them.\nLike this one.
It get's event better.\nDue its fantastic plugin architecture design, you can extend its default modules and use any of these plugins or event write your own to parse however you want.\nThe built-in modules for object parsers are: json, yml, csv and file.\nRun $ nqr -e to see available ones.
You're probably aware by now but it doesn't hurt do emphasize it: enqueuer provides an amazingly powerful plugin extensible architecture.\nIt has several plugins available, but if none of them pleases you, you're free to create your own.\nAlbeit you don't have to share the one you created, we encourage you to do so. Then go ahead and publish yours to npm and add it to our plugins list.
\n
plugin types
\n
So far, you're able to extend enqueuer default behavior in four ways. Using a protocol plugin, an object parser plugin, an asserter plugin and using a report formatter plugin.
\n
protocol
\n
A protocol plugin enables you to use a different publisher/subscription types.\nRun $ nqr -p [protocol-name] to get the full available list:
Each one listed above has a respective example in the examples folder.\nThis one, for instance, provides support for amqp protocol, so you can create this publisher and subscription:
An object parser plugin enables you to read and parse files as you wish.\nThis test example demonstrates how to use it,\nRun $ nqr -e [object-parser-name] to check available ones:
\n
parsers: \n- yml, yaml\n- json\n- file\n- csv\n
\n
This one, for example, provides the ability to read xml files and inject their values like this:
\n
xmlContent: <<xml://path/to/xml/file.xml>>\n
\n
asserter
\n
An asserter plugin provides you a nicely way to use different assertions than these built-in ones.
Run $ nqr -t to get the full available list.\nConsider looking at this test example.
\n
report formatter
\n
A report formatter plugin gives you the ability to export enqueuer reports the way you want.\nRun $ nqr -f [formatter-name] to list available report formatters:
Consider looking at the example of configuration file to see it in use.\nThis one, for instance, generates xUnit like reports from enqueuer's output.
\n
plugin installation
\n
In order to enqueuer get awareness that you want to use a plugin, you have to tell it, right?\nYou can tell enqueuer to use a plugin in three different ways: using it as a command line argument, through the configuration file or letting enqueuer finding it in a default location.
\n
command line
\n
Tell enqueuer to use your plugin through command line this way $ nqr -l <plugin-folder> -l <another-plugin-folder>.\nWhere plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
configuration file
\n
Tell enqueuer to use your plugin through configuration file this way:
Where plugin-folder and another-plugin-folder are the directories where the plugins are installed in.
\n
implicitly
\n
When enqueuer runs, it looks for modules in its same installation directory or in .nqr folder in the home directory, a.k.a. ~/ folder in linux distributions.\nTherefore, if you run:
You'll see that the enqueuer-plugin-amqp plugin will be loaded.\nEvery enqueuer compatible module gets implicitly loaded.\nIn order to be enqueuer compatible, a module has to have an entryPoint exported function in its main file and, in its package.json file, it has to have either 'enqueuer' or 'nqr' as keywords.
\n
Stacker
\n
Looking for a really really good looking an human error proof solution way of writing these requisition files? \nConsider taking a look at stacker: open source, cross-platform, multi protocol client testing tool.\nThe official enqueuer's best friend forever. Do amazing things and change the world with enqueuer’s GUI!\nWith them, you create, manage and run requisitions and and see their results in a really nice way.\nSee this amazing beauty with your own eyes to get an idea of how it works:
\n
\n\n
Open source
\n
We (by 'we' we mean enqueuer's maintainers not the human race, unfortunately) are very opened to any kind of contributions in general.\nAs long as they make sense and add value to the product, you're free to go.\nWe mean it, do it. Even if it's a typo fix in this README file. Go ahead.\nIf you like it but don't want to waste time creating a pull request, no problem either.\nCreate an issue, or, even easier, give it a github star. It's cheap and it doesn't hurt anyone.\nYou know what? Just head up to enqueuer's github repo and keep staring at its repo.\nIt may help somehow.
In order to contribute with some code, you have to follow a few steps.\nFirst of all, get the code:
\n
$ git clone git@github.com:enqueuer-land/enqueuer.git\n$ cd enqueuer\n
\n
Get its dependencies installed:
\n
$ npm install\n
\n
Build it:
\n
$ npm run build\n
\n
Go for it. Make the changes you want.\nAfter everything is done:
\n
$ npm run all\n
\n
Commit it:
\n
$ npm run commit\n
\n
Push it:
\n
$ git push\n
\n
feedback
\n
We'd love to get your feedback!\nIf you have any comments, suggestions, etc. you can reach us here.
\n
\n\n
\n
\n\n\n\n\n
\n
\n\n \n
\n \n\n
\n\n \n\n\n\n\n
\n \n \n You can’t perform that action at this time.\n
\n\n\n \n \n \n \n \n \n \n
\n \n You signed in with another tab or window. Reload to refresh your session.\n You signed out in another tab or window. Reload to refresh your session.\n