Karate : Select 'n' number of random values from an Array - karate

To get 'n' number of random values from the below array whenever i execute the test script. How i can i achieve this into Karate in a feature file.
[
"2972029540",
"2972033041",
"2972030914",
"2972028446",
"2972030851",
"2972026534",
"2972029484"
]

Here you go:
* def random = function(max){ return Math.floor(Math.random() * max) + 1 }
* def data = [ "2972029540", "2972033041", "2972030914", "2972028446", "2972030851", "2972026534", "2972029484" ]
* def count = random(data.length)
* print 'random count is', count
* def temp = data.slice(0, count)
* print temp
Read this for more info: https://stackoverflow.com/a/53975071/143475

Related

Using karate.set to change value of an array

I want to change the values present in an array using karate.set as i am using it in if condition
my code is:
> * def name = ["ankit"]
> * def value = 2
> * eval if ( value == 2) karate.set('name', 'ANKIT_DESAI')
but the value of name is not changing
Assume that as a list and modify value based on index
* def name = ["ankit"]
* def value = 2
* eval if ( value == 2) name[0] = "ANKIT_DESAI"

Karate - Can i send multiple dynamic data in Scenario Outline

Below is the code :
Feature:
Background:
* def Json = Java.type('Json')
* def dq = new Json()
* def result = dq.makeJson()
* def Sku = dq.makeSku()
Scenario Outline: id : <id>
* print '<id>' #From result
* print '<abc>' #From Sku
Examples:
|result|Sku|
The following is the output I need. Is it possible in Karate?
If i have id = {1,2} and abc = {3,4} i want output to be
id = 1 and abc = 3
id = 1 and abc = 4
id = 2 and abc = 3
id = 2 and abc = 4
Also can this be done for more than 2 variable inputs as well?
Write the permutation logic yourself, build an array with the results.
Note that you can iterate over key-value pairs of a JSON using karate.forEach()
Then either use a data-driven loop call (of a second feature file):
# array can be [{ id: 1, abc: 3 }, {id: 1, abc: 4 }] etc
* def result = call read('second.feature') array
Or a dynamic scenario outline:
Scenario Outline:
* print 'id = <id> and abc = <abc>'
Examples:
| array |
Refer:
https://github.com/intuit/karate#data-driven-features
https://github.com/intuit/karate#dynamic-scenario-outline

In Karate how can we verify if the query with where condition has two results?

I have a scenario where the SQL query with a where condition will result in 2 Rows. How can assert if it is resulting in 2 rows? At present, the karate is throwing an error org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected 1, actual 2
* def response = db.readRow( 'SELECT * from database_name.table_name where id = \"'+ id + '\";')
I believe this should help you : https://github.com/intuit/karate#schema-validation
* def foo = ['bar', 'baz']
# should be an array of size 2
* match foo == '#[2]'
Also, you should use db.readRows instead of db.readRow.
* def dogs = db.readRows('SELECT * FROM DOGS')
* match dogs contains { ID: '#(id)', NAME: 'Scooby' }
* def dog = db.readRow('SELECT * FROM DOGS D WHERE D.ID = ' + id)
* match dog.NAME == 'Scooby'

How can I iterate through normal array in karate?

Output of one of my tasks is coming as ['a','b','c']
Now I have to use these values in a DB query
* def queryToGetHotelIdForAvailableCsId = "select id from hotels_hotel where cs_id in ('a','b','c');"
How can I do this in karate ?
It may be better to use a Java helper, but here you go:
* def json = ['a', 'b', 'c']
* def fun =
"""
function(array) {
var temp = '';
for (var i = 0; i < array.length; i++) {
if (i > 0) temp = temp + ',';
temp = temp + "'" + array[i] + "'"
}
return '(' + temp + ')';
}
"""
* def result = fun(json)
* match result == "('a','b','c')"

How to declare constraints with variable as array index in Z3Py?

Suppose x,y,z are int variables and A is a matrix, I want to express a constraint like:
z == A[x][y]
However this leads to an error:
TypeError: object cannot be interpreted as an index
What would be the correct way to do this?
=======================
A specific example:
I want to select 2 items with the best combination score,
where the score is given by the value of each item and a bonus on the selection pair.
For example,
for 3 items: a, b, c with related value [1,2,1], and the bonus on pairs (a,b) = 2, (a,c)=5, (b,c) = 3, the best selection is (a,c), because it has the highest score: 1 + 1 + 5 = 7.
My question is how to represent the constraint of selection bonus.
Suppose CHOICE[0] and CHOICE[1] are the selection variables and B is the bonus variable.
The ideal constraint should be:
B = bonus[CHOICE[0]][CHOICE[1]]
but it results in TypeError: object cannot be interpreted as an index
I know another way is to use a nested for to instantiate first the CHOICE, then represent B, but this is really inefficient for large quantity of data.
Could any expert suggest me a better solution please?
If someone wants to play a toy example, here's the code:
from z3 import *
items = [0,1,2]
value = [1,2,1]
bonus = [[1,2,5],
[2,1,3],
[5,3,1]]
choices = [0,1]
# selection score
SCORE = [ Int('SCORE_%s' % i) for i in choices ]
# bonus
B = Int('B')
# final score
metric = Int('metric')
# selection variable
CHOICE = [ Int('CHOICE_%s' % i) for i in choices ]
# variable domain
domain_choice = [ And(0 <= CHOICE[i], CHOICE[i] < len(items)) for i in choices ]
# selection implication
constraint_sel = []
for c in choices:
for i in items:
constraint_sel += [Implies(CHOICE[c] == i, SCORE[c] == value[i])]
# choice not the same
constraint_neq = [CHOICE[0] != CHOICE[1]]
# bonus constraint. uncomment it to see the issue
# constraint_b = [B == bonus[val(CHOICE[0])][val(CHOICE[1])]]
# metric definition
constraint_sumscore = [metric == sum([SCORE[i] for i in choices ]) + B]
constraints = constraint_sumscore + constraint_sel + domain_choice + constraint_neq + constraint_b
opt = Optimize()
opt.add(constraints)
opt.maximize(metric)
s = []
if opt.check() == sat:
m = opt.model()
print [ m.evaluate(CHOICE[i]) for i in choices ]
print m.evaluate(metric)
else:
print "failed to solve"
Turns out the best way to deal with this problem is to actually not use arrays at all, but simply create integer variables. With this method, the 317x317 item problem originally posted actually gets solved in about 40 seconds on my relatively old computer:
[ 0.01s] Data loaded
[ 2.06s] Variables defined
[37.90s] Constraints added
[38.95s] Solved:
c0 = 19
c1 = 99
maxVal = 27
Note that the actual "solution" is found in about a second! But adding all the required constraints takes the bulk of the 40 seconds spent. Here's the encoding:
from z3 import *
import sys
import json
import sys
import time
start = time.time()
def tprint(s):
global start
now = time.time()
etime = now - start
print "[%ss] %s" % ('{0:5.2f}'.format(etime), s)
# load data
with open('data.json') as data_file:
dic = json.load(data_file)
tprint("Data loaded")
items = dic['items']
valueVals = dic['value']
bonusVals = dic['bonusVals']
vals = [[Int("val_%d_%d" % (i, j)) for j in items if j > i] for i in items]
tprint("Variables defined")
opt = Optimize()
for i in items:
for j in items:
if j > i:
opt.add(vals[i][j-i-1] == valueVals[i] + valueVals[j] + bonusVals[i][j])
c0, c1 = Ints('c0 c1')
maxVal = Int('maxVal')
opt.add(Or([Or([And(c0 == i, c1 == j, maxVal == vals[i][j-i-1]) for j in items if j > i]) for i in items]))
tprint("Constraints added")
opt.maximize(maxVal)
r = opt.check ()
if r == unsat or r == unknown:
raise Z3Exception("Failed")
tprint("Solved:")
m = opt.model()
print " c0 = %s" % m[c0]
print " c1 = %s" % m[c1]
print " maxVal = %s" % m[maxVal]
I think this is as fast as it'll get with Z3 for this problem. Of course, if you want to maximize multiple metrics, then you can probably structure the code so that you can reuse most of the constraints, thus amortizing the cost of constructing the model just once, and incrementally optimizing afterwards for optimal performance.