I am using Gatling for load testing. When I am creating Customer profiles , Customer IDs will be generated. I am able to extract the customer ID and saving in to session variables.
But How to store these values in to a Text file.
please help me.
There's several ways to achieve that.
If you're familiar with Scala, you can:
open a file in your simulation
write into it in a exec(function): https://github.com/excilys/gatling/wiki/Session#wiki-functions
close the file (either register an ActorSystem shutdown hook, or use Gatling 2 snapshot after hook: https://github.com/excilys/gatling/issues/1475)
If this is too complex for you, the most simple way is to use logback:
declare a logger in your simulation with a special name
configure logback so this logger outputs in a dedicated FileAppender
use a pattern that just logs the message
Regarding the second solution, check the logback documentation: http://logback.qos.ch/documentation.html
In the example below I'm saving the extracted NumberIDs out of the SOAP response and then save them into the numbersIDs.csv file so that it can be fed into another Request.
//Variables to store the extracted values of the response
var numberIDs : Seq[String] = _
//Java Writer
val numberIDs_writer = {
val fos = new java.io.FileOutputStream("numbersIDs.csv")
new java.io.PrintWriter(fos,true)
}
val scn = scenario("basicSimulation")
.exec(http("Request_One")
.post("/services")
.body(StringBody(inputXMLpayLoad))
.headers(Request_One_Header)
.check(bodyString.saveAs("Request_Response")) //Save the response in a variable called Request_Response
.check((status.is(200)))
//Extract all numberIDs of the SOAP response
.check(regex("""<NumberId>([\d]+)</NumberId>""")
.findAll
.transform { string => numberIDs = string; string }
.saveAs("numberIDs")))
//Save variable numberIDs into the csv file
.foreach("${numberIDs}", "id") {
exec(session => {
numberIDs_writer.println(session("id").as[String])
session
})
}
Since 2.0.0-M1, infoExtractor hook takes a Session parameter:
https://github.com/excilys/gatling/issues/1004
There's also a builtin that adds the Session content to simulation.log records when the request fails.
https://github.com/excilys/gatling/commit/b7b6299c658d0aa1b88971208eb0c98a9808e37f
You can adapt this example if you just want to log with logback.
class MySimulation extends Simulation with Logging {
def logSessionOnFailure(status: RequestStatus, session: Session, request: Request, response: ExtendedResponse): List[String] = {
if (status == KO) logger.error(session)
Nil
}
val httpConf = http
...
.extraInfoExtractor(logSessionOnFailure)
...
}
Another possibility (not tested, but could work) is to use response transformer (call .transformResponse after .post). In the transformer body you would get a response object from which you can extract the generated ID and append it into a file, collection, etc.. Then just return the original response as the transformation result. This is however not a very nice solution from the design point of view, because your transformation has a side effect.
Related
I'm trying to find out which telemetry-producing sensors (aka singals/time series') are attached to a device using the REST API. The deviceTemplates endpoint has all this information but there is no JSON schema for it's response anywhere. The responses are highly variable and hard to parse. I need a robust solution for any kind of device.
Any help/advice? Could the IoT Hub SDK help?
I would recommend using Json.Net Schema framework. It lets you determine your own custom JSON schema that would fit your needs.
Please refer the following documentation that helps you on how to Load your schema. Once you have the schema determined you can validate it against a device template and confirm if it follows the same pattern.
You can then parse the JSON file using Json.Net to extract the data you may need. Here is sample of the code that extracts contents from a device template. I have used "RS40 Occupancy Sensor.json" device template in my case.
public static void LoadJson()
{
using (StreamReader r = new StreamReader(#"Path to your JSON device template file"))
{
string json = r.ReadToEnd();
try
{
dynamic? array = JsonConvert.DeserializeObject(json);
if (array != null)
{
foreach (var item in array)
{
var contents = item.contents;
//filter contents to get telemetry data or other information
}
}
}
catch (Exception ex) { Console.WriteLine(ex); }
}
I would like to show my requests and responses details in my HTML report.
A feature file example:
Feature: Rest Assured under Cucumber POC
Scenario: Azure Login Scenario
Given Request specifications are set with base uri "https://login.microsoftonline.com/"
When Azure Login Request Executed
Then Verify Status Code is 200
The Runner class is:
#RunWith(Cucumber.class)
#CucumberOptions(
features = "src/main/resources/features",
glue = {""},
tags = "#tests",
plugin = { "pretty",
"json:target/cucumber-reports/Cucumber.json",
"html:target/cucumber-reports"}//reporting plugin
)
public class CucumberRunner {}
The steps are:
#Given("Request specifications are set with base uri {string}")
public void setRequestsSpec(String baseUri){
RequestSpecification spec = new RequestSpecBuilder()
.setBaseUri(baseUri)
.addFilter(new ResponseLoggingFilter())//log request and response for better debugging. You can also only log if a requests fails.
.addFilter(new RequestLoggingFilter())
.build();
testContext().setRequestSpec(spec);
}
#When("^Azure Login Request Executed$")
public void azureLoginExecuted() {
response =
given() //Add x-www-form-urlencoded body params:
.formParam(GRANT_TYPE_KEY, GRANT_TYPE_VALUE)
.formParam(AUTO_TEAM_CLIENT_ID_KEY, AUTO_TEAM_CLIENT_ID_VALUE)
.formParam(AUTO_TEAM_CLIENT_SECRET_KEY, AUTO_TEAM_CLIENT_SECRET_VALUE)
.formParam(RESOURCE_KEY, RESOURCE_VALUE)
.when()
.post(AUTO_TEAM_TENANT_ID + RESOURCE); //Send the request along with the resource
testContext().setResponse(response);
setAuthorizationToken();
}
#Then("Verify Status Code is {int}")
public void verifyStatusCode(int expected_repsonse_code) {
testContext().getResponse().then().statusCode(expected_repsonse_code);
}
Currently I found out how to show those details only in my IntelliJ console:
For example:
#tests
Feature: Rest Assured under Cucumber POC
#tests
Scenario: Azure Login Scenario # src/main/resources/features/poc.feature:5
Given Request specifications are set with base uri "https://login.microsoftonline.com/" # CommonStepsDefinitions.setRequestsSpec(String)
Request method: POST
Request URI: https://login.microsoftonline.com/6ae4e000-b5d0-4f48-a766-402d46119b76/oauth2/token
Proxy: <none>
Request params: <none>
Query params: <none>
and more..
But the HTML report shows only:
Thank you!
You can log the RestAssured output to your cucumber scenario report by just setting up your RequestSpecification filters in this way:
ByteArrayOutputStream requestResponseBuffer = new ByteArrayOutputStream();
PrintStream requestResponsePrintStream = new PrintStream(requestResponseBuffer , true);
List<Filter> loggingFilters = Arrays.asList(
new RequestLoggingFilter(requestResponsePrintStream),
new CucumberReportLoggingFilter(requestResponseBuffer, scenario),
new ResponseLoggingFilter(requestResponsePrintStream)
);
RequestSpecification requestSpecification = RestAssured.given()
.filters(loggingFilters)
:
where the CucumberReportLoggingFilter class looks like this:
class CucumberReportLoggingFilter implements Filter {
ByteArrayOutputStream requestResponseBuffer;
Scenario scenario;
CucumberReportLoggingFilter(ByteArrayOutputStream requestResponseBuffer, Scenario scenario) {
this.requestResponseBuffer = requestResponseBuffer;
this.scenario = scenario;
}
#Override
Response filter(FilterableRequestSpecification requestSpec,
FilterableResponseSpecification responseSpec, FilterContext ctx) {
// Call the next filter(s) which logs the response to the requestResponseBuffer
Response response = ctx.next(requestSpec, responseSpec);
scenario.write(requestResponseBuffer.toString());
return response;
}
}
This solution sandwiches the custom CucumberReportLoggingFilter between the standard RequestLoggingFilter and ResponseLoggingFilter filters.
The sequence of filter events that occur when the RequestSpecification sends a Request is:
The standard RequestLoggingFilter filter() method runs and pretty prints the Request details to the requestResponseBuffer.
The custom CucumberReportLoggingFilter filter() method runs and calls the next filter (which is the standard ResponseLoggingFilter filter).
The standard ResponseLoggingFilter filter() method runs and pretty prints the Response details to the requestResponseBuffer.
Control is returned to the custom CucumberReportLoggingFilter filter() method which sends the contents of the requestResponseBuffer to the cucumber report using the scenario.write() method.
Only write out the messages if the scenario fails
You could modify the above solution as follows:
Remove the CucumberReportLoggingFilter.
Make the requestResponseBuffer variable 'scenario-scoped' (i.e. only have one buffer per scenario).
Have the last #After hook that runs in your stepdefs code check the scenario result and if it is failure, write out the contents of the requestResponseBuffer to the cucumber report.
I can give you some details which might not answer your question fully.
In order to add data to Cucumber HTML report you can use:
#After
public void addDataToReport(Scenario scenario) { //scenario is provided from Cucumber
scenario.write(string with the information about scenario);
}
It won't be formatted and I don't know how to change how the report displays it. Each of the messages will be under each Test Case.
You have to, somehow, pass the information to #After hook.
I hope someone else will answer with more details.
EDIT:
In order to store the info about what Scenario is running at the moment, or even in parallel, we can create a class to store necessary information, based on the Thread, so it will be Thread-safe.
Let's create a class to store Scenario. Let's call it Storage
public class Storage {
private static final HashMap<Thread, Scenario> map = new HashMap<>();
public static void putScenario(Scenario scenario) {
map.put(Thread.currentThread(), scenario);
}
public static Scenario getScenario() {
return map.get(Thread.currentThread());
}
}
Now, we have to somehow get the Scenario. It can be achieved by using #Before hook like this:
public class BeforeHook {
#Before(order = 1)
public void getScenario(Scenario scenario) {
Storage.putScenario(scenario);
}
}
#Before hooks are run before each scenario. We get the information about Scenario and put it in Storage so we know what Scenario is run on what Thread.
Remember that hooks have to be reachable by the glue parameter in Cucumber Runner!
And now, if we want to write additional information to the report:
#Then("Data is saved to the report")
public void data_is_saved_to_the_report() {
System.out.println("Saving data to report");
Storage.getScenario().write("Test data and stuff");
}
We just get current scenario from the Storage and use Scenario.write() method to add information to the report.
It will look like this in the report:
I try to transform flat JSON data from an Event Hub into a DocumentDB. The target structure should look like:
{
"id" : 1
"field_1" : "value_1",
"details" : {
"detail_field_1":"abc",
"detail_field_2":"def"
}
}
Created from source:
{
"id":1,
"field_1" : "value_1",
"detail_field_1":"abc",
"detail_field_2":"def"
}
I checked the documentation of Azure Stream Analytics but there ist no clear description how to create a proper Query.
Who one can help me?
You can leverage the new JavaScript UDF feature to write nested JSON objects to output.
Register a user-defined function, "UDF.getDetails()" as below:
function main(obj) {
//get details object from input payload
var details_obj = {};
details_obj.detail_field_1 = obj.detail_field_1;
details_obj.detail_field_2 = obj.detail_field_2;
return JSON.stringify(details_obj);
}
Then call the UDF in your query to get a string of the nested JSON object.
SELECT
id,
field_1,
UDF.getDetails(input) As details
INTO output
FROM input
Using JavaScript UDF feature, you can return complex JSON.
Example write function.
function main(obj) {
//get details object from input payload
var details_obj = {};
details_obj.detail_field_1 = obj.detail_field_1;
details_obj.detail_field_2 = obj.detail_field_2;
return details_obj;
}
You should not use JSON.stringify since it will make it a string instead of JSON object.
Use it like.
SELECT id, field_1, UDF.getDetails(input) As details
INTO output
FROM input
I try to post an activity entry with the ActivityService class. I want that all my followers and myself can see it.
this.
ActivityStreamService service = new ActivityStreamService();
service.postEntry("#me", "#all", "", jsonObject, header);
I saw my entry but not my follower
With this.
ActivityStreamService service = new ActivityStreamService();
service.postEntry("#public", "#all", "", jsonObject, header);
My follower saw the entry, but I do not see this.
Have anybody an idea which one is the correct combination?
There are a couple of ways...
1 - You can use the Distribution method
http://www-10.lotus.com/ldd/appdevwiki.nsf/xpDocViewer.xsp?lookupName=IBM+Connections+4.5+API+Documentation#action=openDocument&res_title=Distributing_events_ic45&content=pdcontent
openSocial : {
"deliverTo":[
{"objectType":"person",
"id":"tag:example.org,2011:jane"}
]
}
*You will need a special j2ee role in order to distribute this content (trustedApplication Role in WidgetContainer Application)
2 - You can use the ublog
http://www-10.lotus.com/ldd/appdevwiki.nsf/xpDocViewer.xsp?lookupName=IBM+Connections+4.5+API+Documentation#action=openDocument&res_title=Posting_microblog_entries_ic45&content=pdcontent
POST to my board: /ublog/#me/#all
{ "content": "A new test post" }
3 -
Otherwise, you need to do multiple posts
This means than the event would have to be sent separately to each user that is to receive the event. In order to ensure that this can be done more efficiently, an extension to the the Open Social spec allows for a few means of distribution in the data model
I hope this helps.
As well as the openSocial JSON object, you could use to JSON object
For example this JSON snippet:
"to":[
{"objectType":"person", "id":"#me"}.
{"objectType":"person", "id":"#public"}
{"objectType":"community", "id":"xxx-xx-xxx0x0x0x0x0x"}
]
...can be produced by updating your jsonObject like so:
// #me
JsonJavaObject meJson = new JsonJavaObject();
meJson.put("objectType","person");
meJson.put("id","#me");
// #public
JsonJavaObject publicJson = new JsonJavaObject();
publicJson.put("objectType","person");
publicJson.put("id","#public");
// Community
JsonJavaObject communityJson = new JsonJavaObject();
communityJson.put("objectType","community");
communityJson.put("id","xxx-xx-xxx0x0x0x0x0x");
// Shove them all in a list
List<JsonJavaObject> toJson = new ArrayList<JsonJavaObject>();
toJson.add(meJson);
toJson.add(publicJson);
toJson.add(communityJson);
// add to: [...] to the root JsonJavaObject
jsonObject.put("to", toJson ) ;
Also: Here's a video on adding a user to the trustedExternalApplication role.
I'm working on a Photoshop script in JavaScript using ExtendScript. My script allows some user input, and I'd like to save it between uses. That is, I'm looking for a way to save a simple string or numeric value under a particular key so that I'll be able to access it on subsequent uses of the script. Simply put, I want to save a preference for my script. How do I do that?
Even better would be to be able to save at least some preferences on a per-document basis. Is that possible? That is, can I store an arbitrary bit of data with a document?
You can use put/get custom options to save preference parameters that persist across Photoshop launches:
const kMyFlag = app.stringIDToTypeID( "myFlag" );
const kMyNumber = app.stringIDToTypeID( "myNumber" );
const kMySettings = "mySettings";
function saveSettings()
{
var desc = new ActionDescriptor();
desc.putBoolean(kMyFlag, true);
desc.putInteger(kMyNumber, 42);
// "true" means setting persists across Photoshop launches.
app.putCustomOptions( kMySettings, desc, true );
}
function getSettings()
{
var desc = app.getCustomOptions( kMySettings );
return [desc.getBoolean( kMyFlag ), desc.getInteger( kMyNumber )];
}
You have some options. You can create a text file and write to it using the File object:
var prefs = new File("~/desktop/prefs.txt");
prefs.open("w"); // or "a" to append
prefs.writeln("user:lenny;favorite_color:ff6600;likes:sunsets;");
...if you wanted your preferences tied to the script itself.
If you want per-document preferences you could write a string to one of the metadata fields of the file your working on using Document.info like this (using the 'instructions' field but you could use any writable field):
var doc = app.activeDocument;
doc.info.instructions = "user:lenny;favorite_color:ff6600;likes:sunsets;";
//alert(doc.info.instructions); // see, it works!
As for how to actually format the string you could just do it like a simple config file or, if you have a complex user preferences object you could use the XML object to construct and serialize it. JSON would be great for this but there is no JSON object in Extendscript, unfortunately.
For per-document prefs I suggest the use of the XMP Metadata. You can find example snippet here: http://forums.adobe.com/thread/790973. You can leverage AdobeXMPScript library to create your own namespace like it is suggested in the link by Paul Riggott.