Cucumber "Doc Strings" in Serenity Reports - serenity-bdd

We are thinking to make some tests in Cucumber in the way of getting Living Documentation, and the key for the "Living documentation" is that in the "Then" we want to use "Doc Strings" (Json strings).
But, we realized that the "Doc Strings" are not shown in the Serenity Reports.
Is there any possibility to show the "Doc Strings" inside the Serenity Reports?
Thank you!

It is actually possible. I've created an example Git project that shows how to add custom messages to the Serenity test report using the StepEventBus API of Serenity BDD.
The complete code with further explanations is available at: https://github.com/datentyp/stackoverflow.com-questions-47492400-cucumber-doc-strings-in-serenity-reports
public class TestSteps implements En {
public TestSteps() {
Given("some scenario", () -> { /* implement me! */});
When("some step contains some doc string", () -> { /* implement me! */});
/* implement me */
Then("the content of that doc string should be included in the Serenity test report", this::showStepMessage);
}
public void showStepMessage(String message) {
// TODO: escape message string for use in HTML
String escapedMessage = StringUtils.replace(message, " ", " ");
StepEventBus.getEventBus().stepStarted(ExecutedStepDescription.withTitle(escapedMessage));
StepEventBus.getEventBus().stepFinished();
}
}
But note that if you really want to append some JSON Doc Strings to your Then steps than I think you might be trying to do the wrong thing in the first place.
You can capture the actual HTTP request/response that was send over the wire by using serenity-rest-assured. This way your reports will not only include the expected JSON payload but also the HTTP headers and payload of both, the request and the response.
If you are interested in this have a look at the documentation: http://thucydides.info/docs/serenity-staging/#_testing_rest_with_serenity_bdd

Related

Reading parameters from TestNG file

I successfully implemented several tests within TestNG framework, where parameters are being read from xml file.
Here is the example block that is executed as first:
#Parameters({ "country" })
#BeforeSuite(alwaysRun = true)
public void prepareRequest(String country, ITestContext cnt) {
LoginInfoRequestParm loginParms = new LoginInfoRequestParm(country);
Headers reqHeaders = new Headers();
reqHeaders.setHeaders(loginParms);
}
The problem/question is, why does it work only if the ITestContext is specified? Once it is removed, the overall suite is broken and it will never come to the specified method prepareRequest(). I was not able to debug it, because I cannt set breakpoint before the method to be able to see what is going on in TestNG itself.
Thank you for your explanation.
To get out of this situation, try something like this
String myPar = context.getCurrentXmlTest().getParameter("country");
if (myPar == null) {
myPar = "INDIA";
}
now myPar can be used, only thing here is if you run class for debug or any other purpose then we are using INDIA. if we run from testng.xml file then it will take values from that file.

Spring shell 2.0 how to read inputs with mask

Is there any way to mask user inputs in Spring Shell 2.0.x ?
I need to collect password from user.. did not find any shell api to do that.
Thanks!!
Found that LineReader#readLine(msg,mask) provides that option.
All you have to do is inject the LineReader bean.
If you don't want to rely on third party libraries, you can always do a standard Java console input, something like:
private String inputPassword() {
Console console = System.console();
return new String(console.readPassword());
}
Note though that when running this in an IDE, the System.console() might be null. So you should probably handle that if running in an IDE is something you want to support (for testing for example..) something like:
private String inputPassword() {
Console console = System.console();
// Console can be null when running in an IDE
if (console == null) {
System.out.println("WARNING - CAN'T HIDE PASSWORD");
return new Scanner(System.in).next();
}
return new String(console.readPassword());
}

Running Kotlin HTML Builder in the Browser

I am a Java developer that is very new to Kotlin. I love the language though, and I like how easily web applications can be done with it. The problem is that I cannot figure out how to run Kotlin HTML builder files in the browser, so that I can create a basic web page skeleton in kotlin. I can output it in the IDE, but it is silly how hard it seems to be to get it to run in my browser. This may be a dumb question and I'm missing something very obvious, but I can't seem to find the answer online.
Keep in mind that I'm not using the Intelli-J IDE. Would love to, but can't afford to pay out the nose just to do web development in Kotlin. Been using Eclipse.
Thanks in advance.
When you use Kotlin html builders kotlinx.html or any other of that sort, you need to, well, build them in order to get HTML for the browser.
There are no such thing as "Kotlin builder files". Those constructs are plain Kotlin code, so you write them inside your (server?) codebase, compile them and then invoke them to generate HTML responses. This also means you need a (normal Java) router framework, like Spark for example.
To sum up, html-builders are a way to generate HTML strings, so they do not include a way to ship the HTML elsewhere.
Kotlinx itself doesn't have any utilities to send the result to the user's browser. It's just a regular Kotlin code which can create HTML string. You need a way to send it to the user. There are some.
The simplest one is plain old Java servlets. Anybody still using them?
#WebServlet(urlPatterns = arrayOf("/servlet"), loadOnStartup = 1)
class KotlinxHtmlServlet : HttpServlet() {
override fun doGet(request: HttpServletRequest?, response: HttpServletResponse?) {
response!!.setContentType("text/html")
response!!.writer.appendHTML(true).html {
head {
title = "Hello from kotlinx.html + Servlets"
}
body {
h1 { +"Kotlin is awesome" }
p {
+"Read more about "
a("http://kotlinlang.org") {
target = ATarget.blank
+"it"
}
}
}
}
}
}
Spring Boot is very popular today. However, this #Controller will work in vanilla Spring too:
#Controller
class KotlinxHtmlController {
#ResponseBody
#RequestMapping(path = arrayOf("controller"), method = arrayOf(RequestMethod.GET))
fun doGet(): String {
return createHTML(true).html {
head {
title = "Hello from kotlinx.html + Servlets"
}
body {
h1 { +"Kotlin is awesome" }
p {
+"Read more about "
a("http://kotlinlang.org") {
target = ATarget.blank
+"it"
}
}
}
}
}
}
SparkJava is one of the plenty of young Java micro-frameworks. Note, that in case of SparkJava you can just write routes inside your main:
fun main(args: Array<String>): Unit {
get("spark", { request: Request, response: Response ->
createHTML(true).html {
head {
title = "Hello from kotlinx.html + Servlets"
}
body {
h1 { +"Kotlin is awesome" }
p {
+"Read more about "
a("http://kotlinlang.org") {
target = ATarget.blank
+"it"
}
}
}
}
})
}
I'm leaving dependency management, running the app and guessing the correct URLs to access generated pages to you. All of the above examples will result in this HTML:
<html>
<head title="Hello from kotlinx.html + Servlets"></head>
<body>
<h1>Kotlin is awesome</h1>
<p>Read more about it</p>
</body>
</html>
You can also try Dropwizard or Ninja frameworks.
Also, you can take a look at Kara – a web frameworks especially designed for Kotlin – but it is still in alpha stage.
I may be missing something here, but if using kotlinx.html javascript version, the resultant js code does perform as a DOM builder ... can add more if this is what is required.

Understanding seam filter url-pattern and possible conflicts

I made a custom editor plugin, in a Seam 2.2.2 project, which makes file upload this way:
1) config the editor to load my specific xhtml upload page;
2) call the following method inside this page, and return a javascript callback;
public String sendImageToServer()
{
HttpServletRequest request = ServletContexts.instance().getRequest();
try
{
List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
processItems(items);//set the file data to specific att
saveOpenAttachment();//save the file to disk
}
//build callback
For this to work I have to put this inside components.xml:
<web:multipart-filter create-temp-files="false"
max-request-size="1024000" url-pattern="*"/>
The attribute create-temp-files do not seems to matter whatever its value.
But url-pattern has to be "" or "/myUploadPage.seam", any other value makes the item list returns empty. Does Anyone know why?
This turns into a problem because when I use a url-pattern that work to this case, every form with enctype="multipart/form-data" in my application stops to submit data. So I end up with other parts of the system crashing.
Could someone help me?
To solve my problem, I changed the solution to be like Seam multipart filter handle requests:
ServletRequest request = (ServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
try
{
if (!(request instanceof MultipartRequest))
{
request = unwrapMultipartRequest(request);
}
if (request instanceof MultipartRequest)
{
MultipartRequest multipartRequest = (MultipartRequest) request;
String clientId = "upload";
setFileData(multipartRequest.getFileBytes(clientId));
setFileContentType(multipartRequest.getFileContentType(clientId));
setFileName(multipartRequest.getFileName(clientId));
saveOpenAttachment();
}
}
Now I handle the request like Seam do, and do not need the web:multipart-filter config that was breaking other types of request.

How to unit or integration test use of injected messageSource for i18n in Grails 2.0 service

I make use of a message bundle in one of my services in a Grails 2.0 project for internationalized text. The use case is an email subject that is sent via the mail plugin in an asynchronous way, so it really doesn't make sense to have this in a controller or TagLib (given the usual argument of not accessing your text or views in a service). This code works fine in my running Grails app, but I'm not sure how to test it.
I tried a PluginAwareResourceBundleMessageSource in my defineBeans as that is what my running application injects, but it led to nullpointers as it appears it needs a bunch of setup around plugin managers and such that my test environment is not giving (even integration).
I then tried a ReloadableResourceBundleMessageSource as it was pure Spring, but it can't seem to see my .properties files, and fails with a No message found under code 'my.email.subject' for locale 'en'.
I feel like I'm going down a wormhole a bit as accessing Grails i18n in a service is not documented in the grails docs, so if there is a preferred way to do this, let me know.
Note my .properties file is in the standard grails-app/i18n location.
The test
#TestFor(EmailHelperService)
class EmailHelperServiceTests {
void testSubjectsDefaultLocale() {
defineBeans {
//messageSource(PluginAwareResourceBundleMessageSource); Leads to nullpointers
messageSource(ReloadableResourceBundleMessageSource);
}
String expected = "My Expected subject Passed1 Passed2";
String actual = service.getEmailSubjectForStandardMustGiveGiftFromBusiness(Locale.ENGLISH, Passed1 Passed2);
assertEquals("email subject", expected, actual);
}
Service:
class EmailHelperService {
def messageSource;
public String getEmailSubject(Locale locale, String param1, String param2) {
Object[] params = [param1, param2].toArray();
return messageSource.getMessage("my.email.subject", params, locale );
}
There is already a messageSource in unit tests in Grails, it is a StaticMessageSource (see http://static.springsource.org/spring/docs/2.5.4/api/org/springframework/context/support/StaticMessageSource.html), you can add mock messages with the addMessage method:
messageSource.addMessage("foo.bar", request.locale, "My Message")
In unit tests and the local side of functional tests, sometimes you want the real properties that are in the 18n directory.
This works for me:
MessageSource getI18n() {
// assuming the test cwd is the project dir (where application.properties is)
URL url = new File('grails-app/i18n').toURI().toURL()
def messageSource = new ResourceBundleMessageSource()
messageSource.bundleClassLoader = new URLClassLoader(url)
messageSource.basename = 'messages'
messageSource
}
i18n.getMessage(key, params, locale)
In a unit test you could ensure that you're wired up correctly by doing something like this:
void testSubjectsDefaultLocale() {
def messageSource = new Object()
messageSource.metaClass.getMessage = {subject, params, locale ->
assert "my.email.subject" == subject
assert ["Passed1", "Passed2"] == params
assert Locale.ENGLISH == locale
"It Worked!!!"
}
service.messageSource = messageSource
String actual = service.getEmailSubjectForStandardMustGiveGiftFromBusiness(Locale.ENGLISH, Passed1 Passed2)
assert "It Worked!!!" == actual
}
This will help ensure that you're wired up correctly but it will not ensure that what you're doing actually works. If you're comfortable with that then this would work for you. If you're trying to test that when you give "XYZ" to your .properties file it returns "Hello" then this will not work for you.