More information about successful tests? - playwright

How can I provide additional information about a passing test?
console.log doesn't work as the output gets overwritten as the tool logs it's own information about tests. (Perhaps this is a bug?) Ultimately we cannot depend on any output making it to the final screen unless the test fails. Ideally, I want to push an object (and perhaps screenshots) to something that is designed to collect information about the test, then associate it with the test and be accessible with the output of the test.
Building a custom object doesn't work as there are internal features with playwright, such as retry'ing a test.
Here is a typical scenario: While accessing a website, a record may be created (a work order id, or a purchase order number, and various other information may be encountered along the way).
Ideally I'm looking for some object like:
test.addInfo( someObject )
Perhaps at the end of the test, this is dumped out, or available to a reporting tool.

This is possible out-of-the-box. See https://playwright.dev/docs/api/class-testinfo#test-info-annotations
There is an optional second parameter specifically for this. The reporter would have to work with this (json works however list, dot etc.. would not).
test("Some test", async ({ page }, testInfo) => {
// ^ add this object
// Add arbitrary infomation like this:
let someObject = ({ additionalTestInformation: "here" })
testInfo.annotations.push({type:"info", description: someObject });
// Add screenshots or other files as well:
testInfo.attachments.push({ name: "screenshot", path, contentType: "image/png"})
});

Related

Cumulocity smarREST response templates

I am trying to set up the Cumulocity smartREST response templates to supply info from the device object stored by an app. I am thinking it is not possible but I want to confirm because the documentation is brief and not clear.
I have successfully implemented MEASUREMENT POST templates previously but I am trying to do INVENTORY GET now. I have set some values in the device object and I can see them from tenant.cumulocity.com/inventory/managedObjects/id/. This could look like:
"custom_values": {
"val1": "abcde",
"val2": "fghij"
}
Now I go to the smartREST template web interface editor and create a template (eg t1) and set a message (eg m001) and set it to 'inventory' and 'get' and tick 'includes response'. I'm not sure if I need custom fields here. Then I create a response (eg r001) and I now have to fill in base pattern with a condition and some number of other patterns. I assume in one of those fields I have $.custom_values.val1 etc but all permutations I try result in 'no access to object' error from topic 's/e'.
My ideal result (from the above example) would be to publish to '/s/uc/t1' with 'm001' and receive 'r001,abcde' (ie custom_values.val1) and publish 'm002' and receive 'r001,fghij' (ie custom_values.val2).
Thanks for taking the time to read.
Your approach is correct but your MQTT user probably is just missing the rights to the object as it is created by the app (I guess the mqtt client is a device user).
The best approach here is to give this object you are creating from the app the fragment c8y_Global
{
"name": "testObject3",
"c8y_Global": {},
"custom_values": {
"val1": "abcde",
"val2": "fghij"
}
}
This fragment will make this object available to all registered users. This is common practice for app meta data.

Looking for advice on how to normalize format of incoming json from different sources

I am working on a project that receives data (json) from a number of different sources. Each source returns json in a different format, however all services fall into the same category i.e. Issues from Jira and Stories from PivotalTracker each have the same core information.
I am looking for a way to normalize this as much as possible so that I can add other services and formats in the future. Right now I am handling each response type (Jira, PivotalTracker) separately and taking action on each response independently.
So far I am thinking that I'll need a parser for each service, i.e. JiraIssueParser, PivotalTrackerStoryParser etc which transforms the response into a common format that can be used by one method to post onwards, rather than having methods for each to do the receive/parse/post.
Something like this format:
{
issue: {
title: ,
description: ,
assignee: ,
comments: {
1: {
id: ,
title: ,
body:
}
time_entries: {
1: {
id: ,
time: ,
date:
}
}
}
}
I would like to define the common schema somewhere so that each parser's output is always identical. I'm thinking this could be done with a YAML file but I'm not sure how to go about it, and how to use that in the parser.
I would greatly appreciate some suggestions on how to do this. Maybe this is a really stupid question and I should just be outputting the above format from each parser, but I think it would make sense to have some kind of format that is enforced/validated.
Suggestions are appreciated and I'm open to taking a new direction with this if anyone has any ideas. Thanks in advance.
If you're using Rails, I assume then that you are going to have a relational database at some point.
What I would suggest is to define ActiveRecord models that express your "normalized" format: Issue, Comment, TimeEntry, etc.
The job of your parsers, then, is to coerce the JSON data into the appropriate model objects and attributes and save them. Your models thus enforce the canonical data structure (i.e. the schema), and you can even use validators to do further sanity checks.
Finally, I would also save the raw JSON somewhere alongside your model, preferably also in the database. Even though you have already parsed the JSON, keeping it around will come in handy for troubleshooting. For example, if you find and fix a parsing bug, you can re-run the parser on the saved JSON without having to re-download everything the original external sources.

How can I populate a jQuery template (tmpl) using HTML5 Local Storage data

I am trying to build a simple jQuery UI template and populate it with data stored in the localStorage.
I need to set the local storage with a list of guests and have the user edit the list. When clicking update, the changes are sent back to the server.
<ul id="guests">
<li>
Name: ${name} <br />
Phone: ${phone} <br />
Email: ${email}
</li>
</ul>
I am really new at this and have no idea what to do. I am just interested in setting the local storage when the page loads and populating the template.
Can someone please provide a short tutorial?
I thought this is a simple question... Can someone please let me know in case it is not possible at all? Thanks!
you say you want to save the data to localStorage, but also that you want to send modified data to the server.
I would suggest that you divide this problem up into (Part 1) learning how to save locally to localStorage and rendering that content with templating and then (Part 2) learning how to store on a server. I can help you with Part 1, since quite frankly I'm still learning about Part 2 myself.
Okay so, two subtasks:
using localStorage to persist data
using jQuery templates to render data
Using localStorage
You haven't specified where your data is coming from, so I'll assume you have some JSON. For simplicity I'll just use this data:
(You might be wondering why I added content that isn't plain ASCII -- it's just a habit of mine, I believe in testing with realistic text from the get-go. When we finally render this data, it should look right in your browser.)
var philosophers = [
{
"phone": "1-800-123-1937",
"name": "H\u00e9l\u00e8ne Cixous",
"email": "helene#stanford.edu"
},
{
"phone": "1-800-000-0000",
"name": "\u041c\u0438\u0445\u0430\u0438\u0301\u043b \u0411\u0430\u043a\u0443\u0301\u043d\u0438\u043d",
"email": "mikhail#ispitondns.com"
},
{
"phone": "1-800-770-0830",
"name": "Jayar\u0101\u015bi Bha\u1e6d\u1e6da",
"email": "jay#ancientindia.edu"
}
]
So we need to get this into localStorage, just to have some data to start with.
The trick about localStorage is that you can't just directly store JSON objects. You can only store strings. There are some libraries out there designed to improve on this situation, but we'll just convert our objects ourselves. To do that we'll use JSON:
localStorage.philosophers = JSON.stringify(philosophers)
Unsurprisingly, JSON.stringify turns JSON objects into a string, and that can be set directly as an "attribute" of localStorage.
(If you're using an old browser, then you might not have the native JSON object -- there's a library you can include for that too.)
Okay, so now we have some contact data stashed in localStorage with the label of philosophers. (Hey, you never know when you might need to call a philosopher!)
To get that data back out and into a Javascript object we can do something with, we use another JSON method, JSON.parse.
philosophers = JSON.parse(localStorage.philosophers)
This is all pretty artificial, since we've got the philosophers data in the first place, then we stringify it, and then we store it, and then we take it right back out, and then we parse it, and then we're back where we started. But in reality such data will come from some other source -- perhaps an external file or a web service or whatever.
Using templates to render objects
Since you used what looks like jQuery template syntax in your template, I'm going to assume that's the library you're using. The jQuery docs show us how we can render a variable containing some objects (like what we have in our philosophers variable) with a template, here's the key bit of those docs:
// Convert the markup string into a named template
$.template( "summaryTemplate", "<li>${Name}</li>" );
function renderList() {
// Render the movies data using the named template: "summaryTemplate"
$.tmpl( "summaryTemplate", movies ).appendTo( "#moviesList" );
}
Here's one way you can get your template to work (there are other, arguably cleaner methods, but jQuery templates are a topic unto themselves):
var myTemplate = "<li>Name: ${name}<br/>Phone: ${phone}<br/>Email: ${email}</li>";
$.template("contactLi", myTemplate);
That creates a template and stores it in a variable named contentLi. (Note that $.template wants that given variable name given as a string, which strikes me as weird. I find the way jQuery templates names and defines these methods confusing, which is one of the reasons I prefer Mustache for templating. Shrug.)
Also, note that we don't have the ul included in the template, because that's not going to be repeated for each rendered object. Rather, we're going to add the ul as a hook in the markup, and render the assembled template repeatedly as a child of that. Which just takes a single line with jQuery templates, rather nice:
$.tmpl( "contactLi", philosophers ).appendTo( "#guests" );
So there you go, a rendered list.
I know this doesn't answer your whole question but there's a lot here to start with.
Here's an example you can try out, it ends up rendering something like:
Name: Hélène Cixous
Phone: 1-800-123-1937
Email: helene#stanford.edu
Name: Михаи́л Баку́нин
Phone: 1-800-000-0000
Email: mikhail#ispitondns.com
Name: Jayarāśi Bhaṭṭa
Phone: 1-800-770-0830
Email: jay#ancientindia.edu
(Hehe, boy, SO's syntax highlighting doesn't handle that Unicode text very well!)
try AmplifyJS -- can extract your data as json the same way you would as $.getJSON

Is there a way to automatically grab all the elements on the page using Selenium?

When creating tests for .Net applications, I can use the White library to find all elements of a given type. I can then write these elements to an Xml file, so they can be referenced and used for GUI tests. This is much faster than manually recording each individual element's info, so I would like to do the same for web applications using Selenium. I haven't been able to find any info on this yet.
I would like to be able to search for every element of a given type and save its information (location/XPath, value, and label) so I can write it to a text file later.
Here is the ideal workflow I'm trying to get to:
navigate_to_page(http://loginscreen.com)
log_in
open_account
button_elements = grab_elements_of_type(button) # this will return an array of XPaths and Names/IDs/whatever - some way of identifying each grabbed element
That code can run once, and I can then re-run it should any elements get changed, added, or removed.
I can then have another custom function iterate through the array, saving the info in a format I can use later easily; in this case, a Ruby class containing a list of constants:
LOGIN_BUTTON = "//div[1]/loginbutton"
EXIT_BUTTON = "//div[2]/exitbutton"
I can then write tests that look like this:
log_in # this will use the info that was automatically grabbed beforehand
current_screen.should == "Profile page"
Right now, every time I want to interact with a new element, I have to manually go to the page, select it, open it with XPather, and copy the XPath to whatever file I want my code to look at. This takes up a lot of time that could otherwise be spent writing code.
Ultimately what you're looking for is extracting the information you've recorded in your test into a reusable component.
Record your tests in Firefox using the Selenium IDE plugin.
Export your recorded test into a .cs file (assuming .NET as you mentioned White, but Ruby export options are also available)
Extract the XPath / CSS Ids and encapsulate them into a reusable classes and use the PageObject pattern to represent each page.
Using the above technique, you only need to update your PageObject with updated locators instead of re-recording your tests.
Update:
You want to automate the record portion? Sounds awkward. Maybe you want to extract all the hyperlinks off a particular page and perform the same action on them?
You should use Selenium's object model to script against the DOM.
[Test]
public void GetAllHyperLinks()
{
IWebDriver driver = new FireFoxDriver();
driver.Navigate().GoToUrl("http://youwebsite");
ReadOnlyCollection<IWebElement> query
= driver.FindElements( By.XPath("//yourxpath") );
// iterate through collection and access whatever you want
// save it to a file, update a database, etc...
}
Update 2:
Ok, so I understand your concerns now. You're looking to get the locators out of a web page for future reference. The challenge is in constructing the locator!
There are going to be some challenges with constructing your locators, especially if there are more than one instance, but you should be able to get far enough using CSS based locators which Selenium supports.
For example, you could find all hyperlinks using an xpath "//a", and then use Selenium to construct a CSS locator. You may have to customize the locator to suit your needs, but an example locator might be using the css class and text value of the hyperlink.
//a[contains(#class,'adminLink')][.='Edit']
// selenium 2.0 syntax
[Test]
public void GetAllHyperLinks()
{
IWebDriver driver = new FireFoxDriver();
driver.Navigate().GoToUrl("http://youwebsite");
ReadOnlyCollection<IWebElement> query
= driver.FindElements( By.XPath("//a") );
foreach(IWebElement hyperLink in query)
{
string locatorFormat = "//a[contains(#class,'{0}')][.='{1}']";
string locator = String.Format(locatorFormat,
hyperlink.GetAttribute("class"),
hyperlink.Value);
// spit out the locator for reference.
}
}
You're still going to need to associate the Locator to your code file, but this should at least get you started by extracting the locators for future use.
Here's an example of crawling links using Selenium 1.0 http://devio.wordpress.com/2008/10/24/crawling-all-links-with-selenium-and-nunit/
Selenium runs on browser side, even if you can grab all the elements, there is no way to save it in a file. As I know , Selenium is not design for that kinds of work.
You need to get the entire source of the page? if so, try the GetHtmlSource method
http://release.seleniumhq.org/selenium-remote-control/0.9.0/doc/dotnet/html/Selenium.DefaultSelenium.GetHtmlSource.html

How do I associate all logs with their request in grails?

In our grails application we're logging a lot, but need a mechanism to associate all of those messages with the request/response being processed. It has proven easy enough to generate a request UUID, but now I'd like that id appended to each log message generated within a request context without passing that id within each log message. Has anybody implemented such a system so that you can associate all of your log statements together?
A rather obscure feature of log4j, called MDC seems to be exactly what you need.
Something like http://gustlik.wordpress.com/2008/07/05/user-context-tracking-in-log4j/
It will work fine in Grails as well if you use a custom AppFilter to set the request-unique value.
you could try utilizing the RequestContextHolder
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/context/request/RequestContextHolder.html
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
log.debug attr.getRequest().getSession()
Once you get the session object, you can get whatever identifier you have stashed away?

Resources