Specflow/Gherkin: How to handle bad data - specflow

I am new to Specflow so here goes;
For my example below Should I test for the bad at all? If I do the table won't let you add a bad value. So the code will error because its coming in as as bad type. I guess I just need to know how others handle verifying the user can't enter bad data? (fields names are changed due to confidential info)
the requirement says:
Verify that the user cannot set the rate to be negative or greater than 1. The rate range is from 0.9999 to 0.
Verify that the user cannot enter a rate with more than 4 decimal places.
Given the lc does not exist
| Lc |
| Test90 |
| Test00 |
When I add a Lc
| Lc | Somekind of ID| Rate |
| Test90 | 2 | 0.9999 |
| Test00 | 4 | 0 |
Then the lc should be defined
| Lc |
| Test90 |
| Test00 |

It's a bit strange that you are testing 2 values thoughout your test.
I would be tempted to rewrite like this:
Scenario Outline: valid lc's can be created
Given the lc named <lc> does not exist
When I add a Lc named <lc> with Id <id> and rate <rate>
Then the lc named <lc> should be defined
Examples:
| Lc | Id | Rate |
| Test90 | 2 | 0.9999 |
| Test00 | 4 | 0 |
Scenario Outline: Invalid lc's cannot be created
Given the lc named <Lc> does not exist
When I add a Lc named <Lc> with Id <Id> and rate <Rate>
Then the lc named <Lc> should not be defined
And an error should have been raised saying the rate was invalid
Examples:
| Lc | ID | Rate |
| Test90 | 2 | 1.999 |
| Test90 | 2 | 0.99999 |
| Test90 | 2 | -0.9 |
| Test00Y | 4 | 6 |
| Test00Y | 4 | |
The And an error should have been raised saying the rate was invalid step is obviously optional but shows that this is expected to fail due to an invalid rate.

Related

Formula to randomly assign names in a given group with Google Sheets

I would like to create a formula in the below column Assigned so that a random name matching the same group as the current name is automatically inserted.
Names in the Assigned column must match the group of the current name and must not repeat throughout the list. I can't assign the current name with it's own name either. Any suggestions on how to do this?
I guess it is worth posting this. Although it might not be practical for large groups, it is a formula solution that works in Excel and Google sheets:
=INDEX($A$2:$A$8,SMALL(IF(($B$2:$B$8=B2)*($A$2:$A$8<>A2)*(COUNTIF(C$1:C1,$A$2:$A$8)=0),ROW($A$2:$A$8)-1),
RANDBETWEEN(1,SUM(($B$2:$B$8=B2)*($A$2:$A$8<>A2)*(COUNTIF(C$1:C1,$A$2:$A$8)=0)))))
entered as an array formula using CtrlShiftEnter
Here is an example of a successful match:
and an unsuccessful one:
As you can see, Mike, Jack and Fred have paired up together leaving Dave on his own, likewise with Lucy and Harry.
In Excel you may have to press F9 a few times to get a successful result - in Google sheets you just have to keep changing something, or set it to update every minute while you make a cup of tea.
It was my first time to work on something related to unique values, it took time but I learned lot from this question.
Answer of #Tom-Sharpe gave me an inspiration that it can be done, thanks to Tom for that. I tried and here it is.
I have checked it on some random data
+------------+-------+-------------+------------+
| Name | Group | RAND | Assigned |
| Malynda | 1 | 0.644382728 | Boonie |
| Boonie | 1 | 0.167369621 | Venus |
| Venus | 1 | 0.547165865 | Malynda |
| Jamal | 2 | 0.193081046 | Cora |
| Cora | 2 | 0.399459181 | Jamal |
| Alaster | 2 | 0.910498559 | Enrika |
| Enrika | 2 | 0.45819549 | Melisandra |
| Melisandra | 2 | 0.612592303 | Alaster |
| Petunia | 3 | 0.957104883 | Lawton |
| Mariam | 3 | 0.602293619 | Grenville |
| Caterina | 3 | 0.695342797 | Mariam |
| Stace | 3 | 0.942926886 | Caterina |
| Perle1 | 3 | 0.787227158 | Stace |
| Lawton | 3 | 0.315403693 | Perle1 |
| Grenville | 3 | 0.515276361 | Petunia |
| Elia | 4 | 0.655404975 | Catarina |
| Agosto | 4 | 0.322045058 | Fidela |
| Fidela | 4 | 0.490635045 | Agosto |
| Catarina | 4 | 0.121053081 | Elia |
| Elliot | 5 | 0.994137138 | Eddie |
| Mae | 5 | 0.349103119 | Wadsworth |
| Farleigh | 5 | 0.645375865 | Mae |
| Trudey | 5 | 0.473849475 | Farleigh |
| Gwenneth | 5 | 0.678186154 | Trudey |
| Wadsworth | 5 | 0.254168853 | Gwenneth |
| Eddie | 5 | 0.02103249 | Elliot |
| Denyse | 6 | 0.294801945 | Fayina |
| Tracie | 6 | 0.113670327 | Denyse |
| Aili | 6 | 0.901562575 | Tracie |
| Fayina | 6 | 0.029515522 | Alain |
| Mort | 6 | 0.938536467 | Perle |
| Alain | 6 | 0.389741125 | Aili |
| Perle | 6 | 0.513800791 | Mort |
| Mathew | 6 | 0.972656521 | #N/A |
| Benton | 7 | 0.423710316 | Bret |
| Bret | 7 | 0.127478128 | Benton |
| Mayne | 7 | 0.701027869 | Kirbee |
| Derry | 7 | 0.564710572 | Marje |
| Kirbee | 7 | 0.510258205 | Derry |
| Marje | 7 | 0.600908601 | Mayne |
| Devin | 7 | 0.718740939 | #N/A |
| Wilbert | 8 | 0.763761013 | Griswold |
| Brandice | 8 | 0.482092682 | Marty |
| Griswold | 8 | 0.111418464 | Brandice |
| Brandais | 8 | 0.594020577 | Fair |
| Kim | 8 | 0.727863883 | Brandais |
| Cam | 8 | 0.858246187 | Kim |
| Fair | 8 | 0.640979168 | Wilbert |
| Ardath | 8 | 0.883008322 | Cam |
| Marty | 8 | 0.339506717 | Ardath |
+------------+-------+-------------+------------+
D2 contains the below formula
=INDEX(
$A$2:$A$51,
MATCH(
MIN(IF(
(COUNTIF($D$1:D1,$A$2:$A$51)=0)*
($B$2:$B$51=B2)*
($A$2:$A$51<>A2),
$C$2:$C$51)
),
$C$2:$C$51,0)
)
C2 contains just the RAND() function but it is pasted as values so that it doesn't update on every calculation, but if you want you can keep it as a function
There are some #N/A values returned by the formula, it arrives when there is no other person left that can be assigned.
Check it on your data and let me know if it working correctly.
Note that the formula is assuming that names are unique and are sorted based on the groups.
If you're fluent with javascript you could attempt to use Google Apps Script to handle this by going to the toolbar Tools > Script Editor. Another way would be to record a macro via Tools > Macros > Record Macro. The script I generated via this method is below, however I couldn't figure out how to prevent assigning the current name with it's own name. My workaround for that is to select the range of assigned names in the same group and applying Data > Randomize Range until the assignment is satisfactory.
function AppendRandomNameByGroup() {
//Sort based on integer in group column
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).activate();
spreadsheet.getActiveRange().offset(1, 0, spreadsheet.getActiveRange().getNumRows() - 1).sort({column: spreadsheet.getActiveRange().getColumn() + 1, ascending: true});
spreadsheet.getRange('C2').activate();
//Duplicate names to assigned names column
spreadsheet.getRange('A2:A1000').copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
var sheet = spreadsheet.getActiveSheet();
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).activate();
//Filter for each group and randomize items in 'assigned' column
sheet = spreadsheet.getActiveSheet();
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).createFilter();
spreadsheet.getRange('B1').activate();
var criteria = SpreadsheetApp.newFilterCriteria()
.setHiddenValues(['', '2', '3'])
.build();
spreadsheet.getActiveSheet().getFilter().setColumnFilterCriteria(2, criteria);
spreadsheet.getRange('C2:C1000').activate();
spreadsheet.setCurrentCell(spreadsheet.getRange('C4'));
spreadsheet.getActiveRange().randomize();
spreadsheet.getRange('B1').activate();
criteria = SpreadsheetApp.newFilterCriteria()
.setHiddenValues(['1', '', '3'])
.build();
spreadsheet.getActiveSheet().getFilter().setColumnFilterCriteria(2, criteria);
spreadsheet.getRange('C2:C1000').activate()
.randomize();
spreadsheet.getRange('B1').activate();
criteria = SpreadsheetApp.newFilterCriteria()
.setHiddenValues(['2', '', '1'])
.build();
spreadsheet.getActiveSheet().getFilter().setColumnFilterCriteria(2, criteria);
spreadsheet.getRange('C2:C1000').activate();
spreadsheet.setCurrentCell(spreadsheet.getRange('C8'));
spreadsheet.getActiveRange().randomize();
spreadsheet.getActiveSheet().getFilter().remove();
};
If you're trying to set-up a secret santa of some kind, another possible alternative to using scripts would be this Google Sheets Add-On that does something similar including the group functionality that you desire. However instead of assigning a recipient name in-sheet, it requires you to input corresponding e-mail addresses for each name and proceeds to email each participant with their assigned name.
Secret Santa
Sorry that this doesn't fit all your criteria.

SUMPRODUCT with wildcard

I have the SUMPRODUCT working with hardcoded values however I want to use a wild card for the B clomun in my example.
Here is my data
+----------+----------+-----------+
| A COLUMN | B COLUMN | C COLUMN |
+----------+----------+-----------+
| Status | Fruit | Quanitity |
| | | |
| Fresh | Apple | 6 |
| | | |
| Fresh | Apricot | 7 |
| | | |
| Stale | Apple | 4 |
+----------+----------+-----------+
I would like to match Fresh, AP* and then sum the matches form Column C.
I have the following
=SUMPRODUCT(--($B$2:$B$840="AP*"),--($A$2:$A$840="Fresh"),$C$2:$C$840)
Working code with the Wildcard but the count is off
=SUMPRODUCT(ISNUMBER(SEARCH"AP",$B$2:$B$840,1))*($A$2:$A$840="Fresh")*($C$2:$C$840))
The SUMPRODUCT() function does not support wildcards within an array-type expression. The same result can be achieved with:
=SUMPRODUCT((A2:A1000="Fresh")*(LEFT(B2:B1000,2)="Ap")*(C2:C1000))

Rails Many to many relationships with connecting or cloning two table with references?

I'm a new with Rails and I'm having trouble with some types of associations that seem a bit more complex than the ones I've been exposed to so far.
Zombie_users Body_parts_status Body_parts
| id | name | | id | user_id | body_part_id | recovery | | id | name |
|-----------| --> |----------------------------------------| --> |---------------|
| 1 | Joe | | 1 | 1 | 2 | 10% | | 1 | left leg |
| 2 | Max | | 2 | 1 | 3 | 43% | | 2 | brain |
| 3 | hair |
| 4 | blue eye |
Zobmie_users Recovery_tools Body_parts_impacts
| id | name | | id |user_id| name | | id|recovery_tool_id| body_part_id | impact |
|-----------|-->|-------------------|-->|--------------------------------------------|
| 1 | Joe | | 1 | 1 |hammer| | 1 | 1 | 2 | 10% |
| 2 | Max | | 2 | 1 |magic | | 2 | 2 | 3 | 43% |
graphic illustration of the needed functionality
We have users and a list of body parts.
I need that the users will be able to create recovery tools with which they can through Body Parts impact recover their body parts status :)
and be able to check what part of the body still need to be fixed(compared to the list) and what body parts they have already corrected.
My problem is that I do not know how to implement such connections.
because I need to have some kind of clone of the body parts to body parts status for each user.
But how I reference it so it also works with Body Parts impacts
I do not have even a concept of where to start :)
body parts table is just a long listing of all the parts of the human body
and each user should have their own "copy" of all these parts.

Can I have a cucumber example with several values in a single column x row position

Hi here is what I what I have:
Scenario Outline: Seatching for stuff
Given that the following simple things exists:
| id | title | description | temp |
| 1 | First title | First description | low |
| 2 | Second title | Second description with öl | Medium |
| 3 | Third title | Third description | High |
| 11 | A title with number 2 | can searching numbers find this 2 | Exreme |
When I search for <criteria>
Then I should get <result>
And I should not get <excluded>
Examples
|criteria|results | excluded |
| 1 | 1 | 2,3,11 |
| 11 | 11 | 1,2,3 |
| title | 1,2,3 | 11 |
| öl | 2 | 1,3,11 |
| Fir* | 1 | 2,3,11 |
| third | 3 | 1,2,11 |
| High | 3 | 1,2,11 |
As you can see I'm trying to test a search field for a web-application using cucumber and the scenario outline structure in order to test several search criteria.
I'm not sure how to handle the input I would get as result and excluded in my steps.
Maybe this doesn't work at all?
Is there a workaround?
There's nothing wrong with what you're doing. Cucumber will just take that as a single string. The fact that it's actually comma-separated values means nothing to Cucumber.
Your step definition would still look like this:
Then /^I should not get ([^"]*)$/ do |excluded|
# excluded will be a string, "2,3,11"
values = excluded.split(",")
# Do whatever you want with the values
end

SpecFlow - Repeat test X times with list?

Scenario: Change a member to ABC 60 days before anniversary date
Given Repeat When+Then for each of the following IDs:
| ID |
| 0047619101 |
| 0080762602 |
| 0186741901 |
| 0311285102 |
| 0570130101 |
| 0725968201 |
| 0780265749 |
| 0780265750 |
| 0780951340 |
| 0780962551 |
#-----------------------------------------------------------------------
When these events occur:
| WorkflowEventType | WorkflowEntryPoint |
| ABC | Status Change |
Then these commands are executed:
| command name |
| TerminateWorkflow |
And For Member, the following documents were queued:
| Name |
| ABC Packet |
In the above scenario I would like to:
GIVEN - Lookup 10 members from the DB
WHEN + THEN - Do these steps 10 times, once for each record.
Is this possible with SpecFlow?
If so, how would you set it up?
TIA
This is actually quite easy to do, although the documentation takes a bit of searching.
What you want is a scenario outline, like so:
Scenario Outline: Change a member to ABC 60 days before anniversary date
Given I have <memberId>
When these events occur:
| WorkflowEventType | WorkflowEntryPoint |
| ABC | Status Change |
Then these commands are executed:
| command name |
| TerminateWorkflow |
And For <memberId>, the following documents were queued:
| Name |
| ABC Packet |
Examples:
| memberId |
| 0047619101 |
| 0080762602 |
| 0186741901 |
| ...etc... |
This will execute your scenario once for each id in the examples table. You can extend the table to have multiple columns, if needed.
Or, more simply (if you really only have one row in each of your example tables above)
Scenario Outline: Change a member to ABC 60 days before anniversary date
Given I have <memberId>
When A 'ABC' Event Occurs with EntryPoint 'Status Change'
Then a TerminateWorkflow command is executed
And For <memberId>, the 'ABC Packet' document was queued
Examples:
| memberId |
| ...etc... |
For more information see the specflow-wiki on github and the cucumber language syntax for scenario outlines

Resources