I have a command task to call a batch file which returns 1 if File.Ok does not exists and 0 if File.Ok exists in a particular location. Following this command task I have 2 links:
link 1: $commandtask.status = succeeded
link 2: $commandtask.status = failed
After each of these links there are several session and other tasks.
PROBLEM: Whenever File.OK is not found, Link 2 is executed followed by tasks/sessions of this branch (as desired and expected) but after executing all remaining items the workflow gets failed.
note: I have not checked 'Fail Parent if task fails' property anywhere.
You might have checked the "Fail parent if task does not run" in some task. If the task with this property checked does not run then it fails the workflow.
I'm testing API with Postman and I have a problem:
My request goes to sort of middleware, so either I receive a full 1000+ line JSON, or I receive PENDING status and empty array of results:
{
"meta": {
"status": "PENDING",
"missing_connectors_count": 0,
"xxx_type": "INTERNATIONAL"
},
"results": []
}
The question is, how to loop this request in Postman until I will get status SUCCESS and results array > 0?
When I'm sending those requests manually one-by-one it's ok, but when I'm running them through Collection Runner, "PENDING" messes up everything.
I found an awesome post about retrying a failed request by Christian Baumann which allowed me to find a suitable approach to the exact same problem of first polling the status of some operation and only when it's complete run the actual tests.
The code I'd end up if I were you is:
const maxNumberOfTries = 3; // your max number of tries
const sleepBetweenTries = 5000; // your interval between attempts
if (!pm.environment.get("tries")) {
pm.environment.set("tries", 1);
}
const jsonData = pm.response.json();
if ((jsonData.meta.status !== "SUCCESS" && jsonData.results.length === 0) && (pm.environment.get("tries") < maxNumberOfTries)) {
const tries = parseInt(pm.environment.get("tries"), 10);
pm.environment.set("tries", tries + 1);
setTimeout(function() {}, sleepBetweenTries);
postman.setNextRequest(request.name);
} else {
pm.environment.unset("tries");
// your actual tests go here...
}
What I liked about this approach is that the call postman.setNextRequest(request.name) doesn't have any hardcoded request names. The downside I see with this approach is that if you run such request as a part of the collection, it will be repeated a number of times, which might bloat your logs with unnecessary noise.
The alternative I was considering is writhing a Pre-request Script which will do polling (by sending a request) and spinning until the status is some kind of completion. The downside of this approach is the need for much more code for the same logic.
When waiting for services to be ready, or when polling for long-running job results, I see 4 basic options:
Use Postman collection runner or newman and set a per-step delay. This delay is inserted between every step in the collection. Two challenges here: it can be fragile unless you set the delay to a value the request duration will never exceed, AND, frequently, only a small number of steps need that delay and you are increasing total test run time, creating excessive build times for a common build server delaying other pending builds.
Use https://postman-echo.com/delay/10 where the last URI element is number of seconds to wait. This is simple and concise and can be inserted as a single step after the long running request. The challenge is if the request duration varies widely, you may get false failures because you didn't wait long enough.
Retry the same step until success with postman.setNextRequest(request.name);. The challenge here is that Postman will execute the request as fast as it can which can DDoS your service, get you black-listed (and cause false failures), and chew up a lot of CPU if run on a common build server - slowing other builds.
Use setTimeout() in a Pre-request Script. The only downside I see in this approach is that if you have several steps needing this logic, you end up with some cut & paste code that you need to keep in sync
Note: there are minor variations on these - like setting them on a collection, a collection folder, a step, etc.
I like option 4 because it provides the right level of granularity for most of my cases. Note that this appears to be the only way to "sleep" in a Postman script. Now standard javascript sleep methods like a Promise with async and await are not supported and using the sandbox's lodash _.delay(function() {}, delay, args[...]) does not keep script execution on the Pre-request script.
In Postman standalone app v6.0.10, set your step Pre-request script to:
console.log('Waiting for job completion in step "' + request.name + '"');
// Construct our request URL from environment variables
var url = request['url'].replace('{{host}}', postman.getEnvironmentVariable('host'));
var retryDelay = 1000;
var retryLimit = 3;
function isProcessingComplete(retryCount) {
pm.sendRequest(url, function (err, response) {
if(err) {
// hmmm. Should I keep trying or fail this run? Just log it for now.
console.log(err);
} else {
// I could also check for response.json().results.length > 0, but that
// would omit SUCCESS with empty results which may be valid
if(response.json().meta.status !== 'SUCCESS') {
if (retryCount < retryLimit) {
console.log('Job is still PENDING. Retrying in ' + retryDelay + 'ms');
setTimeout(function() {
isProcessingComplete(++retryCount);
}, retryDelay);
} else {
console.log('Retry limit reached, giving up.');
postman.setNextRequest(null);
}
}
}
});
}
isProcessingComplete(1);
And you can do your standard tests in the same step.
Note: Standard caveats apply to making retryLimit large.
Try this:
var body = JSON.parse(responseBody);
if (body.meta.status !== "SUCCESS" && body.results.length === 0){
postman.setNextRequest("This_same_request_title");
} else {
postman.setNextRequest("Next_request_title");
/* you can also try postman.setNextRequest(null); */
}
I was searching for an answer to the same question and thought of a possible solution as I was reading your question.
Use postman workflow to rerun your request every time you don't get the response you're looking for. Anyway, that's what I'm gonna try.
postman.setNextRequest("request_name");
https://www.getpostman.com/docs/workflows
I didn't succeed to find the complete guidelines for this issue that's why I decided to invest some time and to describe all steps of the process from A to Z.
I will be observing an example where we will need to pass through transaction ids and in each iteration to change query param for next transaction id from the list.
Step 1. Prepare your request
https://some url/{{queryParam}}
Add {{queryParam}} variable for changing it from pre-request script.
If you need a token for request you should add it here, in Authorization tab.
Save request to collection (Save button in the right corner). For demonstration purpose I will use "Transactions Request" name. We will need to use this name later on.
Step 2. Prepare pre-request script
In postman use tab Pre-request Script to change transactionId variable from query param to actual transaction id.
let ids = pm.collectionVariables.get("TransactionIds");
ids = JSON.parse(ids);
const id = ids.shift();
console.log('id', id)
postman.setEnvironmentVariable("transactionId", id);
pm.collectionVariables.set("TransactionIds", JSON.stringify(ids));
pm.collectionVariables.get - gets array of transaction ids from collection variables. We will set it up in Step 4.
ids.shift() - we use it to remove id that we will use from our ids list (to prevent running twice on the same id)
postman.setEnvironmentVariable("transactionId", id) - change transaction id from query param to actual transaction id
pm.collectionVariables.set("TransactionIds", JSON.stringify(ids)) - we are setting up a new collection of variables that now does not include the id that was handled.
Step 3. Prepare Tests
In postman use tab Tests to create a loop logic. Tests will be executed after the request execution, so we can use it to make next request.
let ids = pm.collectionVariables.get("TransactionIds");
ids = JSON.parse(ids);
if (ids && ids.length > 0){
console.log('length', ids.length);
postman.setNextRequest("Transactions Request");
} else {
postman.setNextRequest(null);
}
postman.setNextRequest("Transactions Request") - calls a new request, in this case it will call the "Transactions Request" request
Step 4. Run Collections
In Postman from the left side bar you should choose Collections (click on it) and then choose a tab Variables.
This is the collection variables. In our example we used TransactionIds as a variable, so put in Current Value the array of transaction ids on which you want to loop.
Now you can click on Run (the button from right corner, near Save button) to run our loop requests.
You will be proposed to choose on which request you want to perform an action. Choose the request that we’ve created "Transactions Request".
It will run our request with pre-request script and with logic that we’ve set in Tests. In the end postman will open a new window with summary of our run.
I'm using the Jenkins Job DSL plug-in and configured a seed job that is a parameterized build. I would like to fail the build if someone forgets to fill in one of the required parameters. I have the following at the top of my DSL script:
def expectedParams = [
'BRANCH_NAME',
'FALLBACK_BRANCH',
'FOLDER_NAME',
'FOLDER_DISPLAYNAME',
'MAIL_TO'
];
boolean envChecksPass = true;
expectedParams.each {
if (! binding.variables.get(it)?.trim()) {
println "This script expects the $it environment variable to be set."
envChecksPass = false;
}
}
if (! envChecksPass) {
// TODO: SET THE JOB STATUS TO FAILED
return false;
}
How do I complete the TODO bit? Obviously I can throw an Exception here, but it seems a bit ugly. What is the preferred/best practice way.
Throwing an exception is currently the preferred way. If you throw a javaposse.jobdsl.dsl.DslException the stack trace will be suppressed and only the message will be shown.
Another way could be to exit with a non zero code, which will mark the job result as a FAILURE:
if (! envChecksPass) {
// TODO: SET THE JOB STATUS TO FAILED
exit 1;
}
in Jenkins pipelines it is better to use 'error' step
if (! binding.variables.get(it)?.trim()) {
error "This script expects the $it environment variable to be set."
}
you will see the following output in the log (without stack stace)
ERROR: This script expects the USER environment variable to be set.
Finished: FAILURE
I am new to Robot Framework and am trying to figure out how to have multiple statements associated with an If condition.
The basic pre-code counts entries in an array WORDS, and assigns the value to length.
${length}= Get length ${WORDS}
Next I want to do a simple check for the size of the array (should have 10 items).
${status}= Set Variable If ${length} == 10 TRUE FALSE
Now I want to log the result and pass or fail the test case.
Run Keyword If $status == "TRUE"
... Log ${status}
... ELSE
... Log ${status}
Run Keyword If $status != "TRUE"
... FAIL Values do not match
I want to combine the ELSE + logging the status + failing the test case, but can not seem to figure it out. In C programming, I would simply brace the statements between { } and be ok.
In Robot Framework, I have tried 'Run keywords' but with no luck.
... ELSE Run keywords
... Log ${status}
... FAIL Values Do Not Match
I hope there is a way to accomplish this. Appreciate any input.
Using "Run keywords" is the correct solution. However, in order to run multiple keywords you must separate keywords with a literal AND:
... ELSE run keywords
... log ${status}
... AND FAIL Values Do Not Match
You can create keyword with log and fail keywords and pass status as argument, then just use this keyword after ELSE statement.
Or use run keywords like you did, but add AND statement before FAIL (read more here: http://robotframework.org/robotframework/latest/libraries/BuiltIn.html#Run%20Keywords)
Or consider adding ${status} to Fail message: Fail Values Do Not Match. Status: ${status}
Set Test Variable ${temp} rxu
Run Keyword if '${temp}'=='rxu'
... Run Keywords
... Log To Console this is one
... Log To Console This is two
... ELSE Run Keyword Log To Console another block
I am trying to understand when to use PrevTaskStatus vs TaskStatus when defining link conditions in Informatica. I understand PrevTaskStatus takes into account the last task executed by the integration service, ignoring disabled tasks.
But if that is the case, then does PrevTaskStatus return the same value for ALL session objects.
i.e. doesnt $session1.PrevTaskStatus, $session20.PrevTaskStatus both equal SUCCEEDED if session 10 has just completed successfully.
or is $session20.PrevTaskStatus somehow referring to the last task executed PRIOR to $session20, and $session30.PrevTaskStatus somehow refer to a different session.
If I have:
session1 --> session2 --> session3 --> session4
and session 3 is disabled
and I want to put in a link condition from session3 to session4
do I use:
$Start.PrevTaskStatus = SUCCEEDED
$session3.PrevTaskStatus = SUCCEEDED
$session4.PrevTaskStatus = SUCCEEDED
Thanks