Load testing with SOAP UI - web-services

I have a SOAP UI 4.5.1, I have made a load test, it is working fine. My problem is that I run the same request every time and I need to change the values of the soap request I am sending.
For e.g. I have a block of my soap request:
<ns:Assessment>
<ns:Project>
<ns:ProviderId>SHL</ns:ProviderId>
<ns:ProjectId>SampleAssessment</ns:ProjectId>
</ns:Project>
</ns:Assessment>
Provider ID: SHL
Project ID: SampleAssessment
Is there a way to make those values changing from some kind of interval?
For e.g.: Provider IDs [SHL, SLH, LHS]
Project IDs [SampleAssessment, TestAssessment, AnotherAssessment]
And with a load test I am making three request so that for the first request values looks like this:
<ns:Assessment>
<ns:Project>
<ns:ProviderId>SHL</ns:ProviderId>
<ns:ProjectId>SampleAssessment</ns:ProjectId>
</ns:Project>
</ns:Assessment>
for the second like this:
<ns:Assessment>
<ns:Project>
<ns:ProviderId>SLH</ns:ProviderId>
<ns:ProjectId>TestAssessment</ns:ProjectId>
</ns:Project>
</ns:Assessment>
and so on...
Is there a way to make this happen with SOAP UI?

From my experience, you will need to use a Groovy Script step.
For example, if you have a step before your request that is a script, you can use something like:
context.setProperty("ProviderId", "SHL")
Then in your request, use:
<ns:ProviderId>${ProviderId}</ns:ProviderId>
Of course, this doesn't buy you much by itself. There are few ways to vary what the context.setProperty("ProviderId", "SHL") line will set. You can create a collection and iterate over it using something like:
def providers = ['ABC', 'DEF', 'GHI', 'JKL']
providers.each() {
context.setProperty("ProviderId", it)
testRunner.runTestStepByName( "nameofteststep" )
}
Where "nameofteststep" is the name of the Soap Request test step. This might sound odd, but if you right click the test step and disable it, the groovy script will still be able to execute it but it will not run sequentially. By that I mean that the groovy script will run it 4 times, but it won't run a fifth time when the script is complete because it is after the script. Then you just need to keep in mind that each load test thread makes four requests, but I am pretty sure that the SoapUI statistics will take this into account for you... might want to keep an eye out for it, though.
Alternatively, you could check the 'threadIndex' and set a the context variable based on that. A bit like this here: Log ThreadCount.
You could also use a collection without a loop and increment an index that you save as a testcase property and send the string corresponding to the index.
Personally, I think the first way is the most straightforward but I can provide an example of the other ones if you like.

There is a simple way of doing this without writing a groovy script.
After creating a test case you should include the below test steps:
1-Data source
2-Request
3-Loop
Data source will read an excel file (or other data source methods such as XML, groovy, JDBC, gird .. however the excel is the simplest one).
You should include the datas (that you need to change within the request)
Within the test request you need the right click and select "get data" . please notice that your test request should be as below
<ns:ProviderId>${ProviderId}</ns:ProviderId>
Then the last step is the "Loop" . This for returning to the first step until the data ends.
I hope this helps.

Related

Postman: run same test in different Collections

is it possible to write one test in postman and use them for all collections?
I dont want to copy/paste every test into each collection, because I have a lot Collections.
For example to check the response object if its valid and so on.

Obtain folder name in test script

I'm writing API tests using Postman. I'm organizing them into folders by endpoint, and subfolders by test cases within the endpoint folders. There are multiple cases for each endpoint and for each case there are post calls that set up data prior the the csubject-endpoint call that I'm making assertions against.
I already have 100s of calls in this suite. The test runner, unfortunately, does not provide the folder names in its output, so it's difficult to see at a glance which particular case I am looking at when, for example, it reports a test fail.
Is there a convenient way to obtain the folder names for a given call in its test script? With this, I could prepend the case name to the test name, and that would make my tests vastly more readable.
I think a variable containing the current request path in the folder hierarchy would be the best, but for now I didn't find such a feature.
Instead I may suggest such a workaround solution:
In each folder prerequest scripts you set a variable:
pm.environment.set("folder", "folder1/folder1.1/")
the value of folder variable you have to maintain separately for each folder.
Then on a collection level you put a collection test like this:
pm.test("location: " + pm.environment.get("folder"), true)
After running your collection in the Runner you will get the output
from collection tests at the beginning of the test results for each request
showing the folder location.
The effort of setting folder variables pays off when you estimate the results of complex tests. I used to change the names of the requests but it is even more complicated.
UPDATE:
You can also find the info in results hovering over a gray shortcut of path on the left of the request status. A tooltip displays a full path, what in fact eliminates the need of the above solution if you only want to observe the results, but the solution can be useful if you want to make some logs containing the path.
I don't think that there is anything like that from within the application - The closet I can see is the pm.info.requestName function which references the request name that the test belongs too.
This is a basic use case but you could add this to the test name to give you a 'quick glance' and what was run against what request.
pm.test(`${pm.info.requestName} - Status code is 200`, () => {
pm.response.to.have.status(200)
})
If you take a look at Newman it might have something within the summary object that you could extract, in a script, to get the folder name but I've never done this.
Closest thing right now would be this:
I believe I included this in my logged bugs / feature requests out to their team.

How to specify "element(by.id" or "element(by.css" in Ember.js using Protractor

New to ember.js -- used http://yoember.com/ to create a Demo ember.js site. I'm trying to figure out how to use Protractor to test certain elements, but I'm encountering issues specifying them.
Most, but not all, elements (buttons, text areas, etc) have a serialized id value: id='ember###' that changes every time the page is reloaded, which makes it impossible to indicate some elements in Protractor (like, element(by.id('ember557')).sendKeys('foo');).
Running a command like the one above will return the error: Failed: No element found using locator: By(css selector, *[id="ember557"]), which is due to the 3-digit id value changing.
In my demo app, I was able to go into the /app/templates/components/ file for that page and manually add something like id='name' into the handlebars input and was able to successfully find and test that element in Protractor.
This isn't ideal though, and I'd like to find a way to test sites that I don't have the ability to modify the html of.
Can anyone help me wrap my head around this? Thanks.

How to create separate python script for uploading data into ndb

Can anyone guide me towards the right direction as to where I should place a script solely for loading data into ndb. As I wish to upload all data into the gae ndb so that the application could perform query on it.
Right now, the loading of data is in my application. I wish to placed it separately from the main application.
Should it be edited in the yaml file?
EDITED
This is a snippet of the entity and the handler to upload the data into GAE ndb.
I wish to placed this chunk of code separately from my main application .py. Reason being the uploading of this data won't be done frequently and to keep the codes in the main application "cleaner".
class TagTrend_refine(ndb.Model):
tag = ndb.StringProperty()
trendData = ndb.BlobProperty(compressed=True)
class MigrateData(webapp2.RequestHandler):
def get(self):
listOfEntities = []
f = open("tagTrend_refine.txt")
lines = f.readlines()
f.close()
for line in lines:
temp = line.strip().split("\t")
data = TagTrend_refine(
tag = temp[0],
trendData = temp[1]
)
listOfEntities.append(data)
ndb.put_multi(listOfEntities)
For example if I placed the above code in a file called dataLoader.py, where should I call this script to invoke?
In app.yaml alongside my main application(knowledgeGraph.application)?
- url: /.*
script: knowledgeGraph.application
You don't show us the application object (no doubt a WSGI app) in your knowledge.py module, so I can't know what URL you want to serve with the MigrateData handler -- I'll just guess it's something like /migratedata.
So the class TagTrend_refine should be in a separate file (usually called models.py) so that both your dataloader.py, and your knowledge.py, can import models to access it (and models.py will need its own import of ndb of course). (Then of course access to the entity class will be as models.TagTrend_refine -- very basic Python).
Next, you'll complete dataloader.py by defining a WSGI app, e.g, at end of file,
app = webapp2.WSGIApplication(routes=[('/migratedata', MigrateData)])
(of course this means this module will need to import webapp2 as well -- can I take for granted a knowledge of super-elementary Python?).
In app.yaml, as the first URL, before that /.*, you'll have:
url: /migratedata
script: dataloader.app
Given all this, when you visit '/migratedata', your handler will read the "tagTrend_refine.txt" file that you uploaded together with your .py, .yaml, and so on, files in your overall GAE application, and unconditionally create one entity per line of that file (assuming you fix the multiple indentation problems in your code as displayed above, but, again, this is just super-elementary Python -- presumably you've used both tabs and spaces and they show up OK in your editor, but not here on SO... I recommend you use strictly, only spaces, never tabs, in Python code).
However this does seem to be a peculiar task. If /migratedata gets visited twice, it will create duplicates of all entities. If you change the tagTrend_refine.txt and deploy a changed variation, then visit /migratedata... all old entities will stick around and all the new entities will join them. And so forth.
Moreover -- /migratedata is NOT idempotent (if visited more than once it does not produce the same state as running it just once) so it shouldn't be a GET (and now we're on to super-elementary HTTP for a change!-) -- it should be a POST.
In fact I suspect (but I'm really flying blind here, since you see fit to give such tiny amounts of information) that you in fact want to upload a .txt file to a POST handler and do the updates that way (perhaps avoiding duplicates...?). However, I'm no mind reader, so this is about as far as I can go.
I believe I have fully answered the question you posted (though perhaps not the one you meant but didn't express:-) and by SO's etiquette it would be nice to upvote and accept this answer, then, if needed, post another question, expressing MUCH more clearly and completely what you're trying to achieve, your current .py and .yaml (ideally with correct indentation), what they actually do and why you'd like to do something different. For POST vs GET in particular, just study When should I use GET or POST method? What's the difference between them? ...
Alex's solution will work, as long as all you data can be loaded in under 1 minute, as that's the timeout for an app engine request.
For larger data, consider calling the datastore API directly from your own computer where you have the source. It's a bit of a hassle because it's a different API; it's not ndb. But it's still a pretty simple API. Here's some code that calls the API:
https://github.com/GoogleCloudPlatform/getting-started-python/blob/master/2-structured-data/bookshelf/model_datastore.py
Again, this code can run anywhere. It doesn't need to be uploaded to app engine to run.

Create complex-type variables for a Web Service Task

In SSIS, I already have a Web Service Task using a WSDL for sending SMS. I am indeed able to send SMS using this task.
I want supply values to this task from the database, such as Mobile Number, Message body, User ID, etc.
How can I create a complex type user variable that can be passed as input to a Web Service task?
It looks like the only answer is to change the web service to accept only simple types as parameters. I have scoured the web and there seems to be no way to dynamically create complex types for consumption by the input values in the web service task.
The more 'easy' way is to use the script component for bypassing variables to a web service. Check http://amolpandey.com/2016/09/26/ssis-script-task-to-obtain-geo-cordinates-from-address-text-via-google-api/ & http://www.sqlmusings.com/2011/03/25/geocode-locations-using-google-maps-v3-api-and-ssis/.
Tested and working. Using this task you can bypass the SSIS variables/parameters.
Example: Getting ID, addreess, zipcode, city, country from a table with an execute SQL Task. Change Resultset:Full result set on General tab. Then on resultset tab add Result_Name:0 & Variable_Name: User::YourObject. Then the next task will be a Forlooptask editor (Foreach ADO Enumerator ,Collection tab - Ado object source variable: User::YourObject, enumeration mode: rows in the first table, variable Mapping tab - Variable User::Id, 0 | address,1 etc.). Inside the Forlooptask editor you add a data flow task, which the source of this task will be a script component. If you be more specific about your logic,we may assist you more.
Okay so I came across the same problem. I needed to pass one parameter as complex type.
Create a Web Service task in your package.
Fill all the needed properties at General tab: HttpConnection and WSDFile
Fill properties in Input tab: Service, Method
Below click on Value, manually enter the value you need (mine is 2021-11-15)
Deploy and execute package to be sure everything is OK
After this easy steps go into folder where package is localated. Right click on package file (Package.dtsx) and select Open with > Notepad. With find function in notepad search the value you manually inserted.
The part which we are looking for looks in my case like this
<WSTask:ComplexValue>
<WSTask:ComplexProperty
WSTask:Name="date"
WSTask:Datatype="dateTime"
WSTask:ParamType="Primitive">
<WSTask:PrimitiveValue>2021-11-15</WSTask:PrimitiveValue>
</WSTask:ComplexProperty>
</WSTask:ComplexValue>
Finally I found what I was looking for. Now for the second part I needed to be that parameter changing by current date when I execute that package. In powershell I managed to write a code that change date part in string: <WSTask:PrimitiveValue>2021-11-15</WSTask:PrimitiveValue> to current date, everytime when the package is executed. The code looks like this:
$Now = Get-Date -Format "yyyy-MM-dd"
$Yesterday = (Get-Date).AddDays(-1).ToString("yyyy-MM-dd")
$file = ((Get-Content -path "C:\Package.dtsx" -Raw) -replace "<WSTask:PrimitiveValue>$Yesterday</WSTask:PrimitiveValue>", "<WSTask:PrimitiveValue>$Now</WSTask:PrimitiveValue>")
[System.IO.File]::WriteAllText("C:\Package.dtsx",$file)
# This part will execute the package #
dtexec.exe /f "C:\Package.dtsx"
After all this, I planned this script in Task Scheduler and it works.
In my case changing the type of request from complex to simple wasn't an option and all I needed was just one parameter to pass.
Hopes it gonna help somebody.