Page Object Model or JavaScript testing alternatives? - javascript

Is the Page Object Model still the best way to automate web applications ?
For me the Screenplay pattern seems a nicer way to manage it.
Or using JavaScript alternatives like Acceptance Testing with Cucumber.js & WebdriverIO for example.

Your question makes it sound like there is only one answer, but actually you can merge these all together if you code it correctly.
Page Object Model
This is good for separation of the elements on the page from the rest of your code. If implemented correctly, a change on the page can be corrected for all scenarios using that page by simply changing one line in the POM.
nextButton.click();
fullName.sendKeys("John Doe");
Screenplay Pattern
This is good for separation of actions that occur on the different pages, the different workflows.
james.attemptsTo(
goToTheNextPage(),
fillOutHisDetails()
);
If the journey has workflow that is slightly changed, the idea is that you can simply reorder the Screenplay pattern, or remove the actions that are no longer necessary.
In the example above, if the business were to decide that the registration form should be a single page instead of multiple, it would make more sense to delete this single line:
goToTheNextPage(),
instead of deleting the 2 that I would have put in:
driver.findElement({css:"#next"}).click();
driver.findElement({css:"#registrationDetails"});
CucumberJS + WebdriverIO
This is good to portray the information of a scenario in pure business language.
Scenario: I am filling out the registration form
Given I am a new user
And I want to register for an account
When I fill out the registration form
Then I should be able to log in
Merging them
If you want truely human readable code, you can merge all 3 of these.
You have your feature file at business level language.
You have your step definitions written with the Screenplay pattern in mind.
You have the Screenplay pattern steps written with the Page Object Model.
This may seem like a lot of layers, but it means that the business will be able to understand the scenarios, the testers and developers looking back over the code will understand the workflow of a certain journey, and looking further into the code on debugging will allow the tester to change the element values across multiple journeys by only changing one line of code.

Related

In clean architecture between entity layer and use-case layer. What is the use-case boundary?

As I understand Entity caries fundamental properties, methods and validations. An User Entity would have name, DoB...email, verified, and what ever deemed 'core' to this project. For instance, one requires phone number while a complete different project would deem phone number as not necessary but mailing address is.
So then, moving out side of Entity layer, we have the Use-Case layer which depends on entity layer. I imagine this use-case as something slightly more flexible than entity. So this layer allows us to write additional logic and calculations while making use of existing entity or multiple entities.
But my first uncertainty lies whether use-case can create derived values(DoB => Age) from entity properties and even persist them in storage or does it need to already exist in User Entity class already ? Secondly, does use-case layer even NEED to use entity, could I have a use-case that literally just sums(a, b) and may or may not persist that in storage anyways? Thirdly, when persisting entity related properties into database, does retrieving them require once again validation, is this redundant and hurting performance?
Finally, the bigger quesetion is, what is use-case ? should use-case mean to be adaptable by being agnostic of where the inputs comes from and what it serves to? does this just mean the inversion dependency removes the responsibility of what framework it ties to. I.e. using express or Koa or plain http wouldn't force a rewrite of core logic . OR does it mean adaptable to something even greater? like whether it serves directly at the terminal-related applications or api request/response-like-applications via web server?
If its the latter, then it's confusing to me, because it has to be agnostic where it gets/goes, yet these outputs resembles the very medium they will deliver to. for instance, designing a restFUL api, a use case may be...
getUserPosts(userId, limit, offset). which will output a format best for web api consumers (that to me is the application logic right? for a specific application). And it's unlikely that I'll reuse the use-case getUserPost for a different requestor (some terminal interface that runs locally, which wants more detailed response), more or less. So to me i see it shines when the times comes to switch between application-specific framework like between express/koa/httprequest/connect for a restapi for the same application or node.js/bun environment to interact with the same terminal. Rather than all mightly one usecase that criss-cross any kind of application(webservice and terminal simultaneously or any other).
If it is allmighty, should use-case be designed with more generalized purpose? Make them take more configurable? like previously i could've add more parameters getUserPosts(userId, limit, offset, sideloadingConfig, expandedConfig, format: 'obj' | 'csv' | 'json' ), I suppose the forethought to anticipate different usage and scaling requires experience - unless this is where the open-close principle shines to make it ready to be expandable? Or is it just easier to make a separate use-case like getUserPostsWebServices and getUserPostsForLocal , getPremiumUsersPostsForWebServices - this makes sense to me, because now each use-case has its own constraints, it is not possible for WebServieces to reach anymore data fetch/manipulation than PostsForLocal or getPremiumUsersPostsForWebServices offers. and our reusability of WebServices does not tie to any webserver framework. I suppose this is where I would draw the line for use-case, but I'm inexperienced, and I don't know the answer to this.
I know this has been a regurgitation of my understanding rather than a concrete question, but it still points to the quesiton of what the boundary and defintion of use-case is in clean architecture. Thanks for reading, would anyone chime to clarify anything I said wrong?
But my first uncertainty lies whether use-case can create derived values(DoB => Age) from entity properties and even persist them in storage or does it need to already exist in User Entity class already ?
The age of a user is directly derived from the date of birth. I think the way it is calculated is the same between different applications. Thus it is an application agnostic logic and should be placed in the entity.
Defining a User.getAge method does not mean that it must be persisted. The entities in the clean architecture are business object that encapsulate application agnostic business rules.
The properties that are persisted is decided in the repository. Usually you only persist the basic properties, not derived. But if you need to query entities by derived properties they can be persisted too.
Persisting time dependent properties is a bit tricky, since they change as time goes by. E.g. if you persist a user's age and it is 17 at the time you persist it, it might be 18 a few days or eveh hours later. If you have a use case that searches for all users that are 18 to send them an email, you will not find all. Time dependent properties need a kind of heart beat use case that is triggered by a scheduler and just loads (streams) all entities and just persists them again. The repository will then persist the actual value of age and it can be found by other queries.
Secondly, does use-case layer even NEED to use entity, could I have a use-case that literally just sums(a, b) and may or may not persist that in storage anyways?
The use case layer usually uses entities. If you use case would be as simple as sum two numbers it must not use entities, but I guess this is a rare case.
Even very small use cases like sums(a, b) can require the use of entities, if there are rules on a and b. This can be very simple rules like a and b must be positive integer values. But even if there are no rules it can make sense to create entities, because if a and be are custom entities you can give them a name to emphasize that they belong to a critial business concept.
Thirdly, when persisting entity related properties into database, does retrieving them require once again validation, is this redundant and hurting performance?
Usually your application is the only client of the database. If so then your application ensures that only valid entities are stored to the database. Thus it is usually not required to validate them again.
Valid can be context dependent, e.g. if you have an entity named PostDraft it should be clear that a draft doesn't have the same validation rules then a PublishedPost.
Finally a note to the performance concerns. The first rule is measure don't guess. Write a simple test that creates, e.g. 1.000.000 entities, and validates them. Usually a database query and/or the network traffic, or I/O in common, are performance issues and not in memory computation. Of cource you can write code that uses weird loops that mess up performance, but often this is not the case.
Finally, the bigger quesetion is, what is use-case ? should use-case mean to be adaptable by being agnostic of where the inputs comes from and what it serves to? does this just mean the inversion dependency removes the responsibility of what framework it ties to. I.e. using express or Koa or plain http wouldn't force a rewrite of core logic . OR does it mean adaptable to something even greater? like whether it serves directly at the terminal-related applications or api request/response-like-applications via web server?
A use case is is an application dependent business logic. There are different reasons why the clean architecture (and also others like the hexagonal) make them independent of the I/O mechanism. One is that it is independent of frameworks. This makes them easy to test. If a use case would depend on an http controller or better said you implemented the use case in an http controller, e.g. a rest controller, it means that you need to start up an http server, open a socket, write the http request, read the http response, extract the data you need to test it. Even there are frameworks and tools that make such an test easy, these tools must finally start a server and this takes time. Tests that are slow are not executed often, are they? And tests are the basis for refactoring. If you don't have tests or the tests ran slow you do not execute them. If you do not execute them you do not refactor. So the code must rot.
In my opinion the testability is most import and decoupling use cases from any details, like uncle bob names the outer layers, increases the testability of use cases. Use cases are the heart of an application. That's why they should be easy testable and be protected from any dependency to details so that they do not need to be touched in case of a detail change.
If it is allmighty, should use-case be designed with more generalized purpose? Make them take more configurable? like previously i could've add more parameters getUserPosts(userId, limit, offset, sideloadingConfig, expandedConfig, format: 'obj' | 'csv' | 'json' )
I don't think so. Especially the sideloadingConfig, format like json or csv are not parameters for a use case. These parameters belong to a specific kind of frontend or better said to a specific kind of controllers. A use-case provides the raw business data. It is the responsibility of a controller or better a presenter to format them.

Gherkin - maintaining state between scenarios

Although I have been writing unit tests for 20-odd years, I am new to Gherkin, and haven been given the task of implementing a story for a .feature file that reduces to something like this:
Scenario: a
Given that the app is open
When I open a certain dialog
Then it has a thing somewhere
Scenario: b
Given that the dialog from 'a' is open...
# Imagine here a long chain of scenarios, each depending on the previous
Scenario: n
Given that the previous 'n' steps have all completed....
That is, a long, long chain of scenarios, each depending on the state of the system as configured by its predecessor.
This doesn't feel right to someone used to unit testing -- but these scenarios are not going to be split and run separately.
What's the best practice here?
Should I rewrite into one very long scenario?
I am already using a 'page object' to keep most of my code out of the step definitions -- should I be coding the steps as single calls, that can be re-used in the later scenarios?
I'm running Cucumber in Javascript.
First things first, Warning:
For the majority of tests (and by majority I mean 99.9% of the time), you should not carry on from the previous scenario, because of the fact that if one scenario fails in your feature, more will crumble because you attempted to string them together.
And on to my answer:
Depending on whether you are trying to do a set up for all of your scenarios after (within the same feature), or whether you want to reuse that first scenario multiple times (in separate features), you could do one of 2 things.
Make the first scenario a background
Make the first scenario into a step definition, for use in multiple feature files
For the First:
Background:
Given that the app is open
When I open a certain dialog
Then it has a thing somewhere
Scenario: a
Given that the dialog from 'a' is open...
Just remember that when you use it as a background, it will be used for all the following scenarios within that feature.
For the Second:
Scenario: a
Given that the app is open
When I open a certain dialog
Then it has a thing somewhere
Scenario: b
Given I have opened the dialogue from a
And the '<DialogFromA>' dialog is open...
I would ask myself, what is the actual behaviour behind all the steps?
Then I would implement that as the wanted behaviour and push the order between steps down the stack. Probably using one or many helper classes. There is nothing saying that you can force the order of the scenarios without introducing some hack to force them together.
Remember that BDD and Cucumber is all about human readable communication. The dependencies you are asking for should, in my opinion, be implemented in the support code Gherkin triggers.

What are the use cases of jsdom

After reading this Micro templates are dead article. I've become curious:
Whether Using the DOM on the server results in cleaner more maintainable code then templating.
Whether it's more efficient to use jsdom instead of a templating engine.
How to factor jsdom into the View of a standard MVC setup.
And generally in what situations would it be better to use a server-side DOM abstraction, like jsdom rather then a templating engine, like EJS or jade.
The question is specific to node.js and other SSJS
Well, I actually needed JSDom for a small project I built over the weekend in node.js. So, on my server, I had to accept a URL to fetch, grab all of the HTML from the given URL, parse it, and display images to the user so that the user could select a thumbnail from that URL. (Kind of like when you drop a link into the Facebook input box) So, I used a module called Request which allows me to fetch HTML on the server-side. However, when that HTML reached my program, I had no way to traverse it like you do with client-side javascript. Because there was no actual DOM, I couldn't say document.getElementById('someId'). Therefore, JSDom came in handy by giving me a "makeshift" DOM that allowed me to traverse the returned HTML. Now, even though I was still on the server side, JSDOM created a window object very similar to the window object in the browser, and created a DOM out of the returned HTML. Now, even on the server, I was able to get all images by calling window.$('img'). I could target and parse the elements like normal. So, this is just one problem where JSDom turned out to be the solution, but it worked amazingly well. Hope this helps some!
Its a nice abstraction that matches a client side engineers take on how the dom is built and modified. In that respect it is 'cleaner' because there is one mental model. Its also nice because we don't have to mix a kluge of disparate syntaxes from a templating language on top of otherwise clean declarative markup as is the case with even the 'stupidest' templating system, such as mustache.
I would NOT say its more efficient to use jsdom for templating. Go take a gander at google wrt to 'memory leaks with jsdom' for instance. jsdom is rad, and is super useful for tasks like weekend projects for crawling sites, doing non-server related tasks, but I think its slow as shit from a high performance web server perspective.
There are a billion ways to factor this. No method has emerged as a 'standard' way. One way that I've seen is to send down an empty 'template', i.e. a block of html that represents a model in some way, and then use that to bootstrap building your end view from a model. From that article, for example:
<li class="contact" id="contact-template">
<span class="name"></span>
<p class="title"></p>
</li>
This is the 'view' in the classic respect. In the typical web application, it might look something more like:
<li class="contact">
<span class="name"><?= $name ?></span>
<p class="title"><?= $title ?></p>
</li>
To use mvc, one sets up a controller that is vaguely aware of the semantics of the above view and the model it represents. This view is parsed into the/a DOM and accessed via your favorite selector engine. Each time the model this represents changes, you might use change events or callbacks to update the view. For instance:
Lets imagine that 'model' fires a 'change' event every time a property changes.
controller = new Controller({
view: $('#contact-template').clone(), // Assume jquery or whatever
model: aContact
});
// Assume some initialization that sets the view up for the first time
// and appends it to the appropriate place. A la:
// this.view.find('.name').text(model.name);
// this.view.find('.title').text(model.title);
// this.view.appendTo('#contacts')
controller.on('model.name.change', function(name){
this.view.find('.name').text(name);
});
These are what systems like Weld and Backbone.js do for you. They all have varying degrees of assumptions about where this work is taking place (server-side, client-side), what framework you're using (jquery, mootools, etc), and how your changes are being distributed (REST, socket.io, etc).
Edit
Some really useful things you can do with jsdom revolve around integration testing and spidering:
https://github.com/mikeal/spider - general purpose web spider that makes use of node's event based processing and gives you jsdom/jquery to help you easily access the DOM in a programatic way
https://github.com/assaf/zombie - headless browser testing using jsdom/jquery for integration tests
https://github.com/LearnBoost/tobi - similar headless browser testing
Personally, I'd like to see a project that took tobi's approach, but mapped it on top of something like https://github.com/LearnBoost/soda such that we can do cloud based selenium testing without selenese (since imo, it sucks).
A few come to mind:
Sharing views/controllers between server and browser
Data mining / crawling / processing
Transformation for fragments of HTML used in AJAX/realtime stuff
Absolute separation of logic and content by avoiding template tags
And to answer your questions:
maybe. A lot of things affect code quality, but it's a step in the right direction
nope, templating engines will always be faster, since they can pre-compile templates
this probably warrants a new question?
point 2 of your question can be answered by this templating testcase:
go http://jsperf.com/dom-vs-innerhtml-based-templating/300
click the button "Run tests".
be patient, it compares weld vs. a lot of other template engines and gives you the current benchmarks ...

Handling standard user facing scenarios

*I was wondering if i could do all these in javascript, as opposed to having rails helpers
In my application, there are several types of "if-else" UI cases. This is a fairly common scenario, and i wonder if anyone has a tidy way to do these?
EG 1) There might be several types of links with the same behavior: "upvote", etc.
If it is the user's own article, i do not want it to be passed to the server, but pop up a dialog box
EG 2) There might be a several links called "follow", "become a fan", etc
If the user already have done the given action before, it should be a text "followed" instead of a link.
Normally you'd use helpers for this. You write helpers called, based on your examples, upvote_button (which might take a user as a parameter) or follow_button (where this one might take true/false for already-following/not-following.
If you can be more specific as to what you need, I can probably be more specific in my answer.

Ajax Architecture - MVC? Other?

Hey all, I'm looking at building an ajax-heavy site, and I'm trying to spend some time upfront thinking through the architecture.
I'm using Code Igniter and jquery. My initial thought process was to figure out how to replicate MVC on the javascript side, but it seems the M and the C don't really have much of a place.
A lot of the JS would be ajax calls BUT I can see it growing beyond that, with plenty of DOM manipulation, as well as exploring the HTML5 clientside database. How should I think about architecting these files? Does it make sense to pursue MVC? Should I go the jquery plugin route somehow? I'm lost as to how to proceed and I'd love some tips. Thanks all!
I've made an MVC style Javascript program. Complete with M and C. Maybe I made a wrong move, but I ended up authoring my own event dispatcher library. I made sure that the different tiers only communicate using a message protocol that can be translated into pure JSON objects (even though I don't actually do that translation step).
So jquery lives primarily in the V part of the MVC architecture. In the M, and C side, I have primarily code which could run in the stand alone CLI version of spidermonkey, or in the serverside rhino implementation of javascript, if necessary. In this way, if requirements change later, I can have my M and C layers run on the serverside, communicating via those json messages to the V side in the browser. It would only require some modifications to my message dispatcher to change this though. In the future, if browsers get some peer to peer style technologies, I could get the different teirs running in different browsers for instance.
However, at the moment, all three tiers run in a single browser. The event dispatcher I authored allows multicast messages, so implementing an undo feature now will be as simple as creating a new object that simply listens to the messages that need to be undone. Autosaving state to the server is a similar maneuver. I'm able to do full detailed debugging and profiling inside the event dispatcher. I'm able to define exactly how the code runs, and how quickly, when, and where, all from that central bit of code.
Of course the main drawback I've encountered is I haven't done a very good job of managing the complexity of the thing. For that, if I had it all to do over, I would study very very carefully the "Functional Reactive" paradigm. There is one existing implementation of that paradigm in javascript called flapjax. I would ensure that the view layer followed that model of execution, if not used specifically the flapjax library. (i'm not sure flapjax itself is such a great execution of the idea, but the idea itself is important).
The other big implementation of functional reactive, is quartz composer, which comes free with apple's developer tools, (which are free with the purchase of any mac). If that is available to you, have a close look at that, and how it works. (it even has a javascript patch so you can prototype your application with a prebuilt view layer)
The main takaway from the functional reactive paradigm, is to make sure that the view doesn't appear to maintain any kind of state except the one you've just given it to display. To put it in more concrete terms, I started out with "Add an object to the screen" "remove an object from the screen" type messages, and I'm now tending more towards "display this list of objects, and I'll let you figure out the most efficient way to get from the current display, to what I now want you to display". This has eliminated a whole host of bugs having to do with sloppily managed state.
This also gets around another problem I've been having with bugs caused by messages arriving in the wrong order. That's a big one to solve, but you can sidestep it by just sending in one big package the final desired state, rather than a sequence of steps to get there.
Anyways, that's my little rant. Let me know if you have any additional questions about my wartime experience.
At the risk of being flamed I would suggest another framework besides JQuery or else you'll risk hitting its performance ceiling. Its ala-mode plugins will also present a bit of a problem in trying to separate you M, V and C.
Dojo is well known for its Data Stores for binding to server-side data with different transport protocols, and its object oriented, lighting fast widget system that can be easily extended and customized. It has a style that helps guide you into clean, well-divisioned code – though it's not strictly MVC. That would require a little extra planning.
Dojo has a steeper learning curve than JQuery though.
More to your question, The AJAX calls and object (or Data Store) that holds and queries this data would be your Model. The widgets and CSS would be your View. And the Controller would basically be your application code that wires it all together.
In order to keep them separate, I'd recommend a loosely-coupled event-driven system. Try to directly access objects as little as possible, keeping them "black boxed" and get data via custom events or pub/sub topics.
JavaScriptMVC (javascriptmvc.com) is an excellent choice for organizing and developing a large scale JS application.
The architecture design is very practical. There are 4 things you will ever do with JavaScript:
Respond to an event
Request Data / Manipulate Services (Ajax)
Add domain specific information to the ajax response.
Update the DOM
JMVC splits these into the Model, View, Controller pattern.
First, and probably the most important advantage, is the Controller. Controllers use event delegation, so instead of attaching events, you simply create rules for your page. They also use the name of the Controller to limit the scope of what the controller works on. This makes your code deterministic, meaning if you see an event happen in a '#todos' element you know there has to be a todos controller.
$.Controller.extend('TodosController',{
'click' : function(el, ev){ ... },
'.delete mouseover': function(el, ev){ ...}
'.drag draginit' : function(el, ev, drag){ ...}
})
Next comes the model. JMVC provides a powerful Class and basic model that lets you quickly organize Ajax functionality (#2) and wrap the data with domain specific functionality (#3). When complete, you can use models from your controller like:
Todo.findAll({after: new Date()}, myCallbackFunction);
Finally, once your todos come back, you have to display them (#4). This is where you use JMVC's view.
'.show click' : function(el, ev){
Todo.findAll({after: new Date()}, this.callback('list'));
},
list : function(todos){
$('#todos').html( this.view(todos));
}
In 'views/todos/list.ejs'
<% for(var i =0; i < this.length; i++){ %>
<label><%= this[i].description %></label>
<%}%>
JMVC provides a lot more than architecture. It helps you in ever part of the development cycle with:
Code generators
Integrated Browser, Selenium, and Rhino Testing
Documentation
Script compression
Error reporting
I think there is definitely a place for "M" and "C" in JavaScript.
Check out AngularJS.
It helps you with your app structure and strict separation between "view" and "logic".
Designed to work well together with other libs, especially jQuery.
Full testing environment (unit, e2e) + dependency injection included, so testing is piece of cake with AngularJS.
There are a few JavaScript MVC frameworks out there, this one has the obvious name:
http://javascriptmvc.com/

Categories