How do i parameterize parameters i am passing in my API request & execute through Karate? - api

I am testing API's for my application & each API has multiple parameters to be passed, ex. below:
https://abc.xyz.com/***.svc/restful/GetSummary?FromDate=2019/06/28&ToDate=2019/06/28&CompAreaId=15&RegId=4
Each parameter in the request has multiple values (within a defined set of values), so if I want to parameterize each parameter with all the values it could possibly have, how can I create a scenario that will help me achieve this?
I would appreciate any hints/views.
I have been passing parameters as shown in the code below, but unable to pull off the scenario above mentioned, it would be time-consuming & repetitive to pass parameters in a separate scenario each time.
Scenario: Verify if GetContext API returns data with params
Given path 'GetContext'
And param FromDate = '2019/06/27'
And param ToDate = '2019/06/27'
And param CompAreaId = 20
And param RegId = 4
When method get
Then status 200
* def res = response
* print 'response:', response

You can use “Scenario Outline” to achieve that. The following modified code below will run for the 3 rows in the example. (related link: https://github.com/intuit/karate#the-cucumber-way)
Scenario Outline:
Given path 'GetContext'
And param FromDate = '<FromDate>'
And param ToDate = '<ToDate>'
And param CompAreaId = <CompAreaId>
And param RegId = <RegId>
When method get
Then status 200
* def res = response
* print 'response:', response
Examples:
| FromDate | ToDate | CompAreaId | RegId |
| 2019/06/27 | 2019/06/27 | 20 | 4 |
| 2019/06/28 | 2019/06/28 | 21 | 5 |
| 2019/06/29 | 2019/06/29 | 22 | 6 |
Instead of a static count, if you have a dynamic number of rows, you can store the parameter values in a json or CSV and reference it in the example. (related link: https://github.com/intuit/karate#dynamic-scenario-outline)

Related

Print logs only when the tests failed in karate

With Karate API tests, I would like to print the request and reponse only when the test fails.
How can I achieve that in karate.
Consider the below scenarios
Feature: Validate Addition.
Background:
Scenario Outline: Verify Addition
* def sum = <num1> + <num2>
And match sum == 10
* print "number1:" + num1 + " number2:" + num2
Examples:
| num1 | num2 |
| 5 | 5 |
| 7 | 3 |
| 3 | 8 |
| 1 | 5 |
| 1 | 9 |
In the above scenario I get the print for every iteration. Is it possible to print the numbers only when the match fails.
I think it would be more efficient if we can have such option.
Short answer is that it is not possible. You can try contributing code to make this happen. Or maybe you should use REST-assured or Selenium - those sound more like a good fit for you, based on all your questions.
One thought is that you can switch off all logging by making the levels ERROR etc. and then write some custom hook. Refer to hooks here: https://stackoverflow.com/a/60944060/143475
Also refer to how to create custom reports here: https://stackoverflow.com/a/66773839/143475

Karate - How to pass a variable to another feature file using table [duplicate]

This question already has an answer here:
Karate - How to call multiple external features from a single main feature
(1 answer)
Closed 1 year ago.
After doing some reading, I have figured out how to send variables to another feature file. However, how do I pass a variable when I am using a table?
The setup is:
* table valueTable
| number | mode | time | status |
| 12345 | mobile | 100 | 200 |
* call read('feature1.feature#scenario1') valueTable
So if I use the following line to pass variable through, I get failures:
* call read('feature1.feature#scenario1') {table1: '#(valueTable)', payload1: '#(payload)'}
Of course in above, 'payload' is the variable I want to pass to the second feature file. I don't have any issues passing variables if there is no table involved.
Please advise.
Works for me. Put this in a new feature:
* table valueTable
| number | mode | time | status |
| 12345 | 'mobile' | 100 | 200 |
* call read('called.feature') { table1: '#(valueTable)' }
And in called.feature have this:
#ignore
Feature:
Scenario:
* print __arg
And it works fine. So if you are still stuck, please follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue

How to write a select query or server-side function that will generate a neat time-flow graph from many data points?

NOTE: I am using a graph database (OrientDB to be specific). This gives me the freedom to write a server-side function in javascript or groovy rather than limit myself to SQL for this issue.*
NOTE 2: Since this is a graph database, the arrows below are simply describing the flow of data. I do not literally need the arrows to be returned in the query. The arrows represent relationships.*
I have data that is represented in a time-flow manner; i.e. EventC occurs after EventB which occurs after EventA, etc. This data is coming from multiple sources, so it is not completely linear. It needs to be congregated together, which is where I'm having the issue.
Currently the data looks something like this:
# | event | next
--------------------------
12:0 | EventA | 12:1
12:1 | EventB | 12:2
12:2 | EventC |
12:3 | EventA | 12:4
12:4 | EventD |
Where "next" is the out() edge to the event that comes next in the time-flow. On a graph this comes out to look like:
EventA-->EventB-->EventC
EventA-->EventD
Since this data needs to be congregated together, I need to merge duplicate events but preserve their edges. In other words, I need a select query that will result in:
-->EventB-->EventC
EventA--|
-->EventD
In this example, since EventB and EventD both occurred after EventA (just at different times), the select query will show two branches off EventA as opposed to two separate time-flows.
EDIT #2
If an additional set of data were to be added to the data above, with EventB->EventE, the resulting data/graph would look like:
# | event | next
--------------------------
12:0 | EventA | 12:1
12:1 | EventB | 12:2
12:2 | EventC |
12:3 | EventA | 12:4
12:4 | EventD |
12:5 | EventB | 12:6
12:6 | EventE |
EventA-->EventB-->EventC
EventA-->EventD
EventB-->EventE
I need a query to produce a tree like:
-->EventC
-->EventB--|
| -->EventE
EventA--|
-->EventD
EDIT #3 and #4
Here is the data with edges shown as opposed to the "next" column above. I also added a couple additional columns here to hopefully clear up any confusion about the data:
# | event | ip_address | timestamp | in | out |
----------------------------------------------------------------------------
12:0 | EventA | 123.156.189.18 | 2015-04-17 12:48:01 | | 13:0 |
12:1 | EventB | 123.156.189.18 | 2015-04-17 12:48:32 | 13:0 | 13:1 |
12:2 | EventC | 123.156.189.18 | 2015-04-17 12:48:49 | 13:1 | |
12:3 | EventA | 103.145.187.22 | 2015-04-17 14:03:08 | | 13:2 |
12:4 | EventD | 103.145.187.22 | 2015-04-17 14:05:23 | 13:2 | |
12:5 | EventB | 96.109.199.184 | 2015-04-17 21:53:00 | | 13:3 |
12:6 | EventE | 96.109.199.184 | 2015-04-17 21:53:07 | 13:3 | |
The data is saved like this to preserve each individual event and the flow of a session (labeled by the ip address).
TL;DR
Got lots of events, some duplicates, and need them all organized into one neat time-flow graph.
Holy cow.
After wrestling with this for over a week I think I FINALLY have a working function. This isn't optimized for performance (oh the loops!), but gets the job done for the time being while I can work on performance. The resulting OrientDB server-side function (written in javascript):
The function:
// Clear previous runs
db.command("truncate class tmp_Then");
db.command("truncate class tmp_Events");
// Get all distinct events
var distinctEvents = db.query("select from Events group by event");
// Send 404 if null, otherwise proceed
if (distinctEvents == null) {
response.send(404, "Events not found", "text/plain", "Error: events not found" );
} else {
var edges = [];
// Loop through all distinct events
distinctEvents.forEach(function(distinctEvent) {
var newEvent = [];
var rid = distinctEvent.field("#rid");
var eventType = distinctEvent.field("event");
// The main query that finds all *direct* descendents of the distinct event
var result = db.query("select from (traverse * from (select from Events where event = ?) where $depth <= 2) where #class = 'Events' and $depth > 1 and #rid in (select from Events group by event)", [eventType]);
// Save the distinct event in a temp table to create temp edges
db.command("create vertex tmp_Events set rid = ?, event = ?", [rid, event]);
edges.push(result);
});
// The edges array defines which edges should exist for a given event
edges.forEach(function(edge, index) {
edge.forEach(function(e) {
// Create the temp edge that corresponds to its distinct event
db.command("create edge tmp_Then from (select from tmp_Events where rid = " + distinctEvents[index].field("#rid") + ") to (select from tmp_Events where rid = " + e.field("#rid") + ")");
});
});
var result = db.query("select from tmp_Events");
return result;
}
Takeaways:
Temp tables appeared to be necessary. I tried to do this without temp tables (classes), but I'm not sure it could be done. I needed to mock edges that didn't exist in the raw data.
Traverse was very helpful in writing the main query. Traversing through an event to find its direct, unique descendents was fairly simple.
Having the ability to write stored procs in Javascript is freaking awesome. This would have been a nightmare in SQL.
omfg loops. I plan to optimize this and continue to make it better so hopefully other people can find some use for it.

Rails, SQL: private chat, how to find last message in each conversation

I'v got the folowing schema
+----+------+------+-----------+---------------------+--------+
| id | from | to | message | timestamp | readed |
+----+------+------+-----------+---------------------+--------+
| 46 | 2 | 6 | 123 | 2013-11-19 19:12:19 | 0 |
| 44 | 2 | 3 | 123 | 2013-11-19 19:12:12 | 0 |
| 43 | 2 | 1 | ????????? | 2013-11-19 18:37:11 | 0 |
| 42 | 1 | 2 | adf | 2013-11-19 18:37:05 | 0 |
+----+------+------+-----------+---------------------+--------+
from/to is the ID of the user's, message – obviously, the message, timestamp and read flag.
When user open's his profile I want him to see the list of dialogs he participated with last message in this dialog.
To find a conversation between 2 people I wrote this code, it's simple (Message model):
def self.conversation(from, to)
where(from: [from, to], to: [from, to])
end
So, I can now sort the messages and get the last one. But it's not cool to fire a lot of queries for each dialog.
How could I achieve the result I'm looking for with less queries?
UPDATE:
Ok, looks like it's not really clear, what I'm trying to achieve.
For example, 4 users – Kitty, Dandy, Beggy and Brucy used that chat.
When Brucy entered in dialogs, she shall see
Beggy: hello brucy haw ar u! | <--- the last message from beggy
-------
Dandy: Hi brucy! | <---- the last message from dandy
--------
Kitty: Hi Kitty, my name is Brucy! | <–– this last message is from current user
So, three separated dialogs. Then, Brucy can enter anyone dialog to continue private conversation.
And I can't figured out how could I fetch this records without firing a query for each dialog between users.
This answer is a bit late, but there doesn't seem to be a great way to do this, in Rails 3.2.x at least.
However, here is the solution I came up with
(as I had the same problem on my website).
#sender_ids =
Message.where(recipient_id: current_user.id)
.order("created_at DESC")
.select("DISTINCT owner_id")
.paginate(per_page: 10, page: params[:page])
sql_queries =
#sender_ids.map do |user|
user_id = user.owner_id
"(SELECT * FROM messages WHERE owner_id = #{user_id} "\
"AND recipient_id = #{current_user.id} ORDER BY id DESC "\
"LIMIT 1)"
end.join(" UNION ALL ")
#messages = Message.find_by_sql(sql_queries)
ActiveRecord::Associations::Preloader.new(#messages, :owner).run
This gets the last 10 unique people you sent messages to.
For each of those people, it creates a UNION ALL query to get the last message sent to each of those 10 unique people. With 50, 000 rows, the query completes in about ~20ms. And of course to get assocations to preload, you have to use .includes will not work when using .find_by_sql
def self.conversation(from, to)
order("timestamp asc").last
end
Edit:
This railscast will be helpful..
http://railscasts.com/episodes/316-private-pub?view=asciicast
EDIT2:
def self.conversation(from, to)
select(:from, :to, :message).where(from: [from, to], to: [from, to]).group(:from, :to, :country).order("timestamp DESC").limit(1)
end

RavenDB query a scoreboard

Given a scoreboard like this: ie (same score and user allowed)
user | score | date
user1 | 1000 | 10-05-2012
user1 | 999 | 10-05-2012
user2 | 998 | 10-05-2012
user1 | 998 | 10-05-2012
user4 | 987 | 10-05-2012
I d like to query the document for a particular score and get x results below and above
for example say I want to target user2 with score 998 and get 2 above and 2 below
The date is there but doesn't influence the query, when a new score comes in and the same value existed, it would be included below.
What would be the best way to go about it?
at the moment I m doing the worse possible thing, that is to have three queries: one that gets the score I m looking for and then another two to get the some rows above and below.
I've seen some discussion on the GG but I cant make anything that makes sense work, hopefully posting the question here is ok
Update: there is also this thread at the discussion group but it doesn't seem to resolve it either.
Thanks
Miau,
You don't really have a choice, you can drop it to two queries:
var q1 = session.Query<Score>().Where(x=>x.Value >= 998).OrderBy(x=> x.Value).Take(3).ToList();
var q2 = session.Query<Score>().Where(x=>x.Value < 998).OrderByDescending(x=> x.Value).Take(3).ToList();
You can improve on that by using lazy queries:
var q1 = session.Query<Score>().Where(x=>x.Value >= 998).OrderBy(x=> x.Value).Take(3).Lazily();
var q2 = session.Query<Score>().Where(x=>x.Value < 998).OrderByDescending(x=> x.Value).Take(3).Lazily();
Now both queries will be issued against the db in a single request.