Structuring SpecFlow tests as features - bdd

Given that Before/After-Scenario are instance method attributes but Before/After-Feature are static method attributes, is there a way to structure scenarios in a feature file so that they can benefit from each other?
I assume that if there is no way to guarantee the execution order of the scenarios then this would be a purely academic question?
Addendum: When a feature file has multiple scenarios, is the background scenario executed once per scenario or once per feature? This would complicate the answer to the above question, I think(?)

Backgrounds
Background is run once per scenario (every scenario within that feature), i.e:
Feature: Hello World
Background:
Given I go to the homepage
When I search for "Hello, World!"
Scenario: See a result
Then I should see a result
Scenario: See multiple results
Then I should see a maximum of 10 results
Is the same as writing:
Feature: Hello World
Scenario: See a result
Given I go to the homepage
When I search for "Hello, World!"
Then I should see a result
Scenario: See multiple results
Given I go to the homepage
When I search for "Hello, World!"
Then I should see a maximum of 10 results
Scenarios relying on other Scenarios
Scenarios should not depend on each other at all. The order in which the tests are run should be able to change without compromising functionality of the tests.
This will mean setting up your tests on a per scenario basis. One example of this is with Backgrounds (as shown above), or getting to the same point during the "Given" steps.
If I were to do this with the example above:
Feature: Hello World
Scenario: See a result
Given I have searched for "Hello, World!"
Then I should see a result
Scenario: See multiple results
Given I have searched for "Hello, World!"
Then I should see a maximum of 10 results
Instead of doing something like this (struck it out so that it's clear not to do this one):
Feature: Hello World
Scenario: See a result
Given I have searched for "Hello, World!"
Then I should see a result
Scenario: See multiple results
Then I should see a maximum of 10 results

Related

Can a cross-reference data stream be achieved using Code in Zapier. Especifically to generate rows in GSheets from 2 different data streams?

My goal is to create automatic to-do's in several projects in Basecamp 3 on a weekly basis.
To do this, I am using the Schedule app in Zapier which triggers the creation of several rows on a google spreadsheet. These rows then trigger the creation of to-do's in specific projects in Basecamp 3. The input of this rows, should be: project's name (used for the search step), to-do text.
I am using the Formatter App in Zapier to try and achieve this. On a first Formatter action, I am splitting the text using commas of all of the names of our projects and returning all the segments. On a second Formatter, I am splitting the text of all the to-do's text and, again, returning all the segments.
Formatter 1 Input (Projects): AA,BB,CC,DD
Formatter 2 Input (To-Do's Text): buy it, use it, break it, fix it
Now, the goal I am trying to achieve is illustrated in the attached diagram. Also illustrated is what the zap (as it is) is achieving with the data. Data Stream Diagrams
We work often with Grasshopper, a Rhino 3D plug-in used for parametric modeling and data-drive design. In grasshopper this would be called a "cross-referenced" data-stream. Is this possible to achieve using Code in Zapier? If so, can I get a little help?
Thanks!
Zapier Zap GIF: https://drive.google.com/open?id=0B85_sQemABgmQVd6MENRd0NsNGc
I don't have permission to view your Google drive link, but I think I get the gist of what you're trying to do.
Rather than use Formatter, you're probably better off using Python as you'll have more control over what's getting returned. You can use Python's itertools.product to get every combination of your two lists.
# zapier runs in a vanilla python environment
# so you can import standard packages
import itertools
letters = ['AA', 'BB', 'CC', 'DD']
actions = ['buy it', 'use it', 'break it', 'fix it']
combos = list(itertools.product(letters, actions))
# [('AA', 'buy it'), ('AA', 'use it'), ... ('DD', 'fix it')]
From there, you'll want to format that list as your action step expects (probably via a list comprehension such as [{'code': c[0], 'action': c[1]} for c in combos] and return the list from the code step.
A hidden feature of Zapier is that if an array is returned from a code step, the zap will run the action for each array element. Be careful though, that means for each input to the zap, the output will be run 16x (which can quickly eat into your task limit).
Hopefully that sets you on the right track. Let me know if somethings was unclear!

How can I cluster similar type of sentences based on their context and extract keywords from them

I wanted to cluster sentences based on their context and extract common keywords from similar context sentences.
For example
1. I need to go to home
2. I am eating
3. He will be going home tomorrow
4. He is at restaurant
Sentences 1 and 3 will be similar with keyword like go and home and maybe it's synonyms like travel and house .
Pre existing API will be helpful like using IBM Watson somehow
This API actually is doing what you are exactly asking for (Clustering sentences + giving key-words):
http://www.rxnlp.com/api-reference/cluster-sentences-api-reference/
Unfortunately the algorithm used for clustering and the for generating the key-words is not available.
Hope this helps.
You can use RapidMiner with Text Processing Extension.
Insert each sentence in a seperate file and put them all in a folder.
Put the operators and make a design like below.
Click on the Process Documents from files operator and in the right bar side choose "Edit list" on "Text directories" field. Then choose the folder that contains your files.
Double click on Process Documents from files operator and in the new window add the operators like below design(just the ones you need).
Then run your process.

How to test a method that filters on several conditions?

I'd like to improve specs for a convenience method that returns an array of users whose purchases are due tomorrow and will be paid using a certain payment method (ignoring other payment methods).
The specs are something along the lines of:
it "doesn't return users without purchases being due tomorrow" do
# create user and associated records that don't fit the time condition
expect(subject).to eq([])
end
context "with users who have purchases due tomorrow" do
it "returns users with $CERTAIN_PAYMENT_METHOD" do
# create different users with different payment methods,
# all matching the time condition.
expect(subject).to eq([user_1, user_2])
end
it "doesn't return users without $CERTAIN_PAYMENT_METHOD" do
# create user with credit card,
# matching the time condition.
expect(subject).to eq([])
end
end
I see three possible approaches here:
Approach used above: Set up arbitrary combinations of records, and expect things specific to a single condition, always asserting the whole array. The setup can be long and repetitive.
Set up arbitrary combinations, and expect things to be included/excluded in the returned array. These "soft expectations" are great to read but can be very error-prone.
Set up (nearly) all combinations of records, and have a single expectation. This creates no overlap but also leaves developers in the dark as to why this method returns this specific array.
All approaches have their drawbacks, and I'm wondering if there's a best practice how to test methods like these?
Deciding between Option 1 and 2 can be tricky, but Option 3 is without a doubt the worst option. Unit Tests serve two purposes* - they drive clean code design and they document what the code does for the developers of the future. As you have correctly pointed out, having "one huge test" leaves developers in the dark as to why the method behaves as it does, and therefore destroys half of the benefit of the tests. Furthermore, these kinds of tests are not the sort of tests that drive out clean code design, so you are probably loosing that benefit too.
Whether Option 1 or 2 is better depends on your situation. Repetitive set up code is not necessarily a problem (research DAMP vs DRY with respect to TDD) and if it is a problem it could be improved by extracting common set up code so it can be shared between test cases (although this can be a smell if taken too far). In any case, I don't see how Option 2 solves the issue of repetitive set up code - the only difference between the two options is how you make the assertions.
The issue of "stock" vs "weak" assertions is a common theme (research strict mocks vs loose mocks) and is the main difference between Option 1 and 2. The problem with Option 1 is that making 1 change to production code can result in having to change the assertions for every single test case. For this reason I would advise having a couple of tests that assert on the whole array (to test ordering and completeness etc) but for most tests to be as specific as possible and only test include/excludes. This allows the test to clearly document which types of set ups result in which output values, rather than every test having a long list of assertions, only one of which is interesting to the current test case.
The guiding principal is, don't test the same thing twice. If, by asserting every element in every test, you feel like you are testing the same thing twice then it's probably not the right way to go.
* OK, sometimes they catch bugs too, but on their own they don't tell you that your system works and is bug free. That is the purpose of other forms of testing that test your entire system. Green unit tests do not give you enough confidence to release to production.

Create a user assistant using NLP

I am following a course titled Natural Language Processing on Coursera, and while the course is informative, I wonder if the contents given cater to what am I looking for.Basically I want to implement a textual version of Cortana, or Siri for now as a project, i.e. where the user can enter commands for the computer in natural language and they will be processed and translated into appropriate OS commands. My question is
What is generally sequence of steps for the above applications, after processing the speech? Do they tag the text and then parse it, or do they have any other approach?
Under which application of NLP does it fall? Can someone cite me some good resources for same? My only doubt is that what I follow now, shall that serve any important part towards my goal or not?
What you want to create can be thought of as a carefully constrained chat-bot, except you are not attempting to hold a general conversation with the user, but to process specific natural language input and map it to specific commands or actions.
In essence, you need a tool that can pattern match various user input, with the extraction or at least recognition of various important topic or subject elements, and then decide what to do with that data.
Rather than get into an abstract discussion of natural language processing, I'm going to make a recommendation instead. Use ChatScript. It is a free open source tool for creating chat-bots that recently took first place in the Loebner chat-bot competition, as it has done so several times in the past:
http://chatscript.sourceforge.net/
The tool is written in C++, but you don't need to touch the source code to create NLP apps; just use the scripting language provided by the tool. Although initially written for chat-bots, it has expanded into an extremely programmer friendly tool for doing any kind of NLP app.
Most importantly, you are not boxed in by the philosophy of the tool or limited by the framework provided by the tool. It has all the power of most scripting languages so you won't find yourself going most of the distance towards your completing your app, only to find some crushing limitation during the last mile that defeats your app or at least cripples it severely.
It also includes a large number of ontologies that can jump-start significantly your development efforts, and it's built-in pre-processor does parts-of-speech parsing, input conformance, and many other tasks crucial to writing script that can easily be generalized to handle large variations in user input. It also has a full interface to the WordNet synset database. There are many other important features in ChatScript that make NLP development much easier, too many to list here. It can run on Linux or Windows as a server that can be accessed using a TCP-IP socket connection.
Here's a tiny and overly simplistic example of some ChatScript script code:
# Define the list of available devices in the user's household.
concept: ~available_devices( green_kitchen_lamp stove radio )
#! Turn on the green kitchen lamp.
#! Turn off that damn radio!
u: ( turn _[ on off ] *~2 _~available_devices )
# Save off the desired action found in the user's input. ON or OFF.
$action = _0
# Save off the name of the device the user wants to turn on or off.
$target_device = _1
# Launch the utility that turns devices on and off.
^system( devicemanager $action $target_device )
Above is a typical ChatScript rule. Your app will have many such rules. This rule is looking for commands from the user to turn various devices in the house on and off. The # character indicates a line is a comment. Here's a breakdown of the rule's head:
It consists of the prefix u:. This tells ChatScript a rule that the rule accepts user input in statement or question format.
It consists of the match pattern, which is the content between the parentheses. This match pattern looks for the word turn anywhere in the sentence. Next it looks for the desired user action. The square brackets tell ChatScript to match the word on or the word off. The underscore preceding the square brackets tell ChatScript to capture the matched text, the same way parentheses do in a regular expression. The ~2 token is a range restricted wildcard. It tells ChatScript to allow up to 2 intervening words between the word turn and the concept set named ~available_devices.
~available_devices is a concept set. It is defined above the rule and contains the set of known devices the user can turn on and off. The underscore preceding the concept set name tells ChatScript to capture the name of the device the user specified in their input.
If the rule pattern matches the current user input, it "fires" and then the rule's body executes. The contents of this rule's body is fairly obvious, and the comments above each line should help you understand what the rule does if fired. It saves off the desired action and the desired target device captured from the user's input to variables. (ChatScript variable names are preceded by a single or double dollar-sign.) Then it shells to the operating system to execute a program named devicemanager that will actually turn on or off the desired device.
I wanted to point out one of ChatScript's many features that make it a robust and industrial strength NLP tool. If you look above the rule you will see two sentences prefixed by a string consisting of the characters #!. These are not comments but are validation sentences instead. You can run ChatScript in verify mode. In verify mode it will find all the validation sentences in your scripts. It will then apply each validation sentence to the rule immediately following it/them. If the rule pattern does not match the validation sentence, an error message will be written to a log file. This makes each validation sentence a tiny, easy to implement unit test. So later when you make changes to your script, you can run ChatScript in verify mode and see if you broke anything.

Can tags in Rspec be ANDed or ORed?

In Cucumber, I had something like this
#do_this
#de #fr #it #us
Scenario: Do something irrelevant
Given ...
When ...
Then
#do_that
#de #fr #it #us
Scenario: Do a different irrelevant thing
Given ...
When ...
Then
It was possible to do something like cucumber -t #de -t #do_this, so only scenarios which matched both tags would be run. I can't seem to get the same behavior in Rspec, though. In the above example, only the first scenario would run, even though the second one also has a #de tag.
Background: I have a platform which is rolled out in many countries, and not all features are available in every country. So the nice thing was that I could just tag the scenarios accordingly, and then call individual scenarios from the command line. I am currently in the process of switching to Rspec from Cucumber because of several reasons, but this is the only thing holding me back at the moment. Of course I am also open for other suggestions on how to approach this.
Short version: I would like to call individual tests in Rspec who match two or more tags.
RSpec tag expressions are only ORed for inclusion and ANDed for exclusion, so you can't do what you want in general. Further, it appears that you can use either tag filters or a filter on the example descriptions, but not both, so I think that combining those two techniques is out as well. (Perhaps someone can correct me on this).
However, if you have a limited/structured situation implied by your example, I think you can do the following:
Define a boolean tag for each of the languages and use the traditional inclusion filter
Define a do tag with values of this, that, etc. and use a lambda exclusion filter which will exclude everything but the value(s) you want.
If you do the above, you will be able so specify examples which contain any of the languages you want and whatever subset of the do values you want
However, I doubt there is a way to specify the lambda expression format in the command line so I think you're limited to using the configuration option approach. In any event, see http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/Configuration:filter_run_excluding for a description of the underlying capability.
That's a lot of limitations, I know. This seems like an area where RSpec could be fairly easily extended, so perhaps we'll see extensions in the future.

Resources