I am doing web automation testing, for example lets say I have two very basic scenarios:
Test a) step 1: add record to the database step
2: check if website
displayed record properly
Test b) step 1: edit record on the website step
2: check if record
were properly saved in database
By record, let say it was simple text field with some "value"
So for first scenario, I would use Assert equal:
private void check1()
{
Assert.assertEquals(valueFromDB, valueOnWebsite)
//many more assertions for more values here
}
but, for second scenario, it would be:
private void check2()
{
Assert.assertEquals(valueOnWebsite, valueFromDB)
//many more assertions for more values here
}
So basically they both do the same, but are inverted, in order to throw correct error log if assertion was incorrect, now how to make it in single method, that could work for both cases, BUT would display correct assertion log if values were not equal?
Use the overload which receives a message
String message = String.format("valueFromDB value: %s, valueOnWebsite value: %s", valueFromDB, valueOnWebsite);
Assert.assertEquals(message, valueFromDB, valueOnWebsite);
If you want to override the built in message you need to do your own implementation
if (!valueFromDB.equals(valueOnWebsite)) {
throw new AssertionFailedError(String.format("valueFromDB value: %s, valueOnWebsite value: %s", valueFromDB, valueOnWebsite));
}
Related
I know it could be a duplicate, but still posting my question as i could not find the exact answer what i am looking for. I am having an json object (or string) like below.
String str = "{
"status" : {
"timestamp" : "2020-04-30T01:00:00 000Z"
"error" : 0,
"error_message" : null,
"execution" : "completed"
}
}
";
I will get the a same kind of response from my REST API testing, but after each call the 'timestamp' key will be having a dynamic date and time value with the time respect to the call made. And here i compare my expect json with the actual json as a whole sting comparison using JSONAssert. As the timestamp value is different it always fails for me.
So my question is before i do any comparison, i would like to remove the 'timestamp' key and its value from json to compare and so it will pass my case. I tried by using JsonPath also, but did not works. Any help on this please?
JSONAssert allow you to make a customized comparator while doing asserts [1].
In your case it's easy as:
JSONAssert.assertEquals(expectedJson,
actualJson,
new CustomComparator(JSONCompareMode.LENIENT,
skips("status.timestamp","another.json.path", ...)));
private static Customization[] skips(String... jsonPaths) {
return Arrays.stream(jsonPaths)
.map(jsonPath -> Customization.customization(jsonPath, (o1, o2) -> true))
.toArray(Customization[]::new);
}
Here we are defining CustomComparator, with customization which takes JSONPath (status.timestamp) and takes a ValueMatcher (lambda) which compares two values for that specific JSONPath.
In our case we will always return true, which will effectively skips the value (no matter with what we are comparing that value it's always true).
Edit: As you can see CustomComparator's constructor takes varargs of Customizations, hence you can provide more than one field to be ignore from comparison.
[1] http://jsonassert.skyscreamer.org/apidocs/org/skyscreamer/jsonassert/Customization.html
[2] http://jsonassert.skyscreamer.org/apidocs/org/skyscreamer/jsonassert/comparator/CustomComparator.html
I'm writing an application with Spring boot 2. My method try to generate value until the value will be unique. Each unique generated value is added to the cache. Generally, it should generate value with the first try, but the more application run - more chance that generated value will have duplicates, and it will be required to generate it again.
I want to have the metric, shows the percentile of tryToGenerate values.
Let's say my code looks the following:
public void generateUniqueValue() {
String value;
int tryToGenerate = 0;
do {
tryToGenerate ++
value = generateRandom();
boolean unique = isUniqueValue(value);
} while (!unique);
addGeneratedValueToCache(value);
}
I'm using micrometer, but have no idea what should I start with. Becase in order to calculate percentile I need to store not the single value, but the array of the values
To determine the result of isUniqueValue(..), you're already storing the used values already. You can use that storage to create a proper metric.
Let's assume that you're storing each used value within a list called usedIds. Additionally, let's say you're generating a unique number between 0 and 1000.
In that case, you could write a method like this:
public float getPercentageUsed() {
return (float) usedIds.size() / 1000;
}
Now you can create a Gauge to add this value to the metrics. Let's say that the class that's used to generate unique values is called UniqueValueService, and it's a proper Spring bean. In that case, you could create a Gauge bean like this:
#Bean
public Gauge uniqueValueUsedGauge(MeterRegistry registry, UniqueIdService service) {
return Gauge
.builder("unique-values-used", service::getPercentageUsed)
.baseUnit("%")
.description("Percentage of possible unique values that have been used")
.register(registry);
}
Edit: It seems I've misunderstood your question. If you want to get a histogram of tryToGenerate, to see how many attempts succeed within the first, second or nth attempt, you can use a DistributionSummary. For example:
#Bean
public DistributionSummary summary(MeterRegistry registry) {
return DistributionSummary
.builder("unique-value-attempts")
.sla(1, 5, 10)
.publishPercentileHistogram()
.register(registry);
}
In this example, it will count how many calls succeeded within the 1st, 5th or 10th attempt.
In your service, you can now autowire the DistributionSummary and at the end of the loop, you can use it like this:
do {
tryToGenerate++
value = generateRandom();
boolean unique = isUniqueValue(value);
} while (!unique);
distributionSummary.record(tryToGenerate); // Add this
Now you can use /actuator/metrics/unique-value-attempts.histogram?tag=le:1 to see how many calls succeeded within the first try. The same can be done with the 5th and 10th try.
Morning,
Seem to be having a brainfart! Have had a look around and can't see any one else having the same issue so I've either completely missed something (most likely) or nobody else has this use case.
I basically want to return all objects stored in a mongodb collection, including their id's, however as the string representation rather than the full object. So this:
public ArrayList findAllObjects(){
return db.getCollection("objects").find().into(new ArrayList<Document>());
}
{
_id: {
class: "org.bson.types.ObjectId",
counter: 7230903,
date: "2016-10-03T12:39:38Z",
machineIdentifier: 5652488,
processIdentifier: 8859,
time: 1475498378000,
timeSecond: 1475498378,
timestamp: 1475498378
},
name: "Test Object"
},
Now if I run a find on the mongo console I get something along the lines of:
{
"_id": ObjectId("57f2518a564008229b6e55b7"),
"name": "Test Object"
}
It's this 57f2518a564008229b6e55b7 that I'd like to return in the original json as the _id (potentially could add under another name) field.
I can get that string representation in the java code simply by running get getObjectId() on an individual document. So I could possibly loop through every result and set/add the _id but that feels like a bit of a smell to me.
Any suggestions would be welcome.
Thanks
Update:
Thanks Sinclair for the comments, I don't believe this is a duplicate though, as I do actually want to include the id not necessarily exclude anything. If the string representation was in the org.bson.types.ObjectId object as a property I could then potentially exclude the rest but that isn't the case.
You can convert the object to string simply using the toString() method:
List<Document> documents = collection.find().into(new ArrayList<>());
documents.parallelStream().forEach(document -> {
document.put("_id", document.get("_id").toString());
});
I am working on automation in jbehave. I have scenario in which i have multiple steps. Now out of that 2 steps are having same input parameter name. For one i am passing value from examples table and for other i am passing value in statement itself even though it is taking value from example table only.
I know i can change the input parameter name in java/jbehave statement but that is not possible because both the statements are used at multiple times and for one scenario i can not break all existing scenarios.
Any clue on this or anyone who faced similar situation should also comment on this.
code snippet
story file
Scenario :
Given I pass value '1'
And I take value from temp file '<value>'
Examples
value |
2
java file :
#Given("I pass value '$value'")
public void fn(#Named("value") int value)
{
------
}
#Given("I take value from temp '$value'")
public void fn2(#Named("value") int value)
{
-----
}
Now the issue here is that for first statement even though i am passing value '1' from statement it is taking value from example table only which is '2'.
I tested a similar scenario on versions 3.9.5 and 4.0.4 of JBehave, and it worked fine on both versions.
This is my scenario:
Scenario: some scenario
Given I pass value '1'
Given I take value from temp file '<value>'
Examples:
|value|
|2|
|3|
and here is my java code:
public class MySteps {
#Given("I pass value '$value'")
public void fn(int value)
{
System.out.println("GIVEN : I pass value = " + value);
}
#Given("I take value from temp file '$value'")
public void fn2( #Named("value") int value)
{
System.out.println("GIVEN : I take value from temp = " + value);
}
}
I have created a project in Eclipse using maven jbehave-simple-archetype.
You can clone this project into Eclipse from this link: https://github.com/kordirko/jb_test
To change a version just edit it in pom.xml => <jbehave.core.version>3.9.5</jbehave.core.version>
========== EDIT ================
Consider setting useDelimiterNamedParameters(true) option in JBehve configuration
http://jbehave.org/reference/stable/parametrised-scenarios.html
They write in documentation, that starting from version 4.0.4 this option is enabled by default.
We can configure JBehave to interpret the name contained between the delimiters as the parameter name and look it up in the parameters provided by the examples table. The default behaviour of parameter lookup is overridden via the ParameterControls:
new MostUsefulConfiguration()
.useParameterControls(new ParameterControls().useDelimiterNamedParameters(true));
In this mode, the step method would look much simplified:
#Given("a stock of $symbol and a $threshold")
public void aStock(String symbol, double threshold) {
// ...
}
Starting from version 4.0, the use of delimiter named parameters is the default behaviour.
I tested this option and it seemed to work both in 3.9.5 and 4.0.4 versions.
This is a test scenario:
Scenario: some scenario
Given I pass value '1'
Given I pass value '<value>'
........
Examples:
|value|
|2|
|3|
and a java method without #Named annotation:
#Given("I pass value '$value'")
public void fn(int value)
{
System.out.println("GIVEN : I pass value = " + value);
}
The first step Given I pass value '1' is taking 1 as a parameter.
The second step Given I pass value '<value>' matches <value> by name with a column named <value> from the example table, and is taking values from this table.
The situation is easy. I created a rules file:
package org.domain.rules;
dialect "mvel"
import eu.ohim.fsp.core.configuration.domain.xsd.Section;
global java.lang.String sectionName;
rule "rule 1"
salience 1000
when
Section($name : nameOfTheSection)
eval(sectionName == null)
then
System.out.println("Section: " + $name+ "("+$name.length()+")");
System.out.println("Section Name: " + sectionName + "("+sectionName.length()+")");
System.out.println("Mark Details: " + sectionName.equals(null));
end
And before firing the rules I added the Section object with a valid coreName and the globals:
public void fireInserted(Section section1) {
kstateful.insert(section1);
kstateful.setGlobal("sectionName", new String("markudetails"));
kstateful.fireAllRules();
}
The result is:
Section: markudetails(12)
Section Name: markudetails(12)
Mark Details: false
QUESTION: How can it be possible? in when part is null and in then part is not null!!!
Global vars are not a part of the knowledge base, but a separate channel to push some context into the rule execution. It is not appropriate to use them in a when clause. The exact reason why it was null in your case may be hard to trace, since rule activation is completely decoupled from rule execution. The variable may simply not be bound at when clause evaluation time, but is bound at then clause execution time.
To summarize: don't use globals in a when clause, that's not what they are for.
Your problem has an easy general solution: you can insert a configuration object into the knowledge. That object can have your desired "sectionName" property which you will then find easy to test in a when.
As an aside, it is meaningless to test for object.equals(null) -- this can never produce true. There is also no need to use new String("markudetails"). Instead use just "markudetails".