In Specflow, although I know about the Scenario Outline / Examples feature, I was wondering if there is a more elegant way to generate ranges and combinations to be used in test cases?
For example, in vanilla NUnit, I can use a TestCaseSource or Theory to build a generator which I can feed in a large number of test cases into a test.
private static readonly IEnumerable<int> Numbers = Enumerable.Range(1, 50);
[TestCaseSource(nameof(Numbers))]
public void TestFoo(int number)
{
// Test goes here.
}
At present, in my tests, I need to manually create all permutations in my Examples, which can be hard to read, and potentially error prone.
Scenario Outline: Count things
Given I'm playing a game of counting
When I count to <number>
Then the highest number I should have counted to should be <number>
Examples:
| number|
| 1 |
| 2 |
| 3 |
...
| 50 |
What I would really like to be able to do would be
Examples:
| number| : Range 1 to 20
And even better, create the cartesian product of two sets, i.e.:
Examples:
| number1| : Range 1 to 20
| number2| : Range 5 to 10
// i.e. 20 x 5 = 100 combinations of the tuple (number1, number2)
Is there anyway for me to approach this more elegantly in Specflow?
You can dynamically generate the range of numbers from two inputs as a step.
For example:
Scenario Outline: Count things
Given I'm playing a game of counting
When I count from <First Number> to <Last Number>
Then the highest number I should have counted to should be <Last Number>
Examples:
| Description | First Number| Last Number |
| Count from 1 to 20 | 1 | 20 |
| Count from 5 to 10 | 5 | 10 |
And then the When step can be defined as something like this:
[When("I count from (\d+) to (\d+)")]
public void ICountFromFirstNumberToLastNumber(int firstNumber, int lastNumber)
{
IEnumerable<int> numbers = Enumerable.Range(firstNumber, lastNumber);
this.countResult = this.Count(numbers);
}
Cucumber is not designed to for doing this sort of testing. When you are cuking each scenario is going to have a runtime which is one or more orders of magnitude slower than a well written unit test. So generating large numbers of scenarios makes your test suite unusable.
Cucumber is all about using scenarios to create a few basic interactions to drive the development of some functionality. Its not a test tool!
To test exhaustively some aspect of functionality keep on using unit tests.
Related
I started to get a headache around my problem that I cannot figure out for the love of me.
There are unknown amounts of column if that makes any difference, but basically each row needs to be compared to the previous one and ONLY when the previous value is greater, the difference between them gets added to the sum.
So for example I have this table
| A |
--|-----|
1 | 100 |
2 | 90 |
3 | 80 |
4 | 100 |
5 | 70 |
6 | 20 |
7 | 100 |
...
Expected result: 100, derived from ((100-90) + (90-80) + (100-70) + (70-20))
I have spent a whole day browsing every single excel tutorial page and cannot find a single helpful answer. Please help :(
Formula for Cell B2: (pull down through the rows).
=IF(A1>B1;A1-B1;0)+B1
Logic: If previous value is larger than current value, add the difference to the total.
If you want to do it in one formula, a basic way would be two use two ranges offset by one cell:
=SUMPRODUCT((A1:A6-A2:A7)*(A1:A6>A2:A7))
If you wanted to make a bit more dynamic (assuming there are no gaps in the data) you could try
=SUMPRODUCT((A1:INDEX(A:A,COUNT(A:A)-1)-A2:INDEX(A:A,COUNT(A:A)))*(A1:INDEX(A:A,COUNT(A:A)-1)>A2:INDEX(A:A,COUNT(A:A))))
If there are blanks between numbers, this won't work and you would probably need to go back to a simpler pull-down formula
I have this excel table
Status | Priority |
-------------------
Yes | High |
No | Medium |
N/A | Medium |
Yes | Low |
A bit | Bonus |
| |
| |
Each priority has a point value. Priority points can change to anything. They aren't in order. Note that lines can also be blank. Assuming that if priority is blank then status is also blank.
High = 3 points
Medium = 2 Points
Low = 1 Point
Bonus = 1 Point
Status's can be blank or any value. However if they are the following then they have coniditions:
Yes = Full point (eg. Yes with High priority gives 3 points) or (eg. Yes with Bonus gives 1 point).
A bit = Half a point (eg. A little with High priortiy gives half 1.5 points) or (eg. A little with Medium gives 1 point). Essentially halving the point.
If the Status is Yes then I want it to count the corresponding point value. So for the table above it should count up 4.5 points.
3 Points for Row 2
1 Point for Row 5
0.5 points for Row 6
I was wondering how I can do this?
I was going to do the following, but it only has one condition.
=COUNTIF(A2:A5, "Yes")
Using Tables and Named Ranges with structured references gives you a great deal of flexibility.
I first set up two tables
priorityTbl
statusTbl
With our Input, I Named the two Ranges Status and Priority
The total is then given by the formula:
=SUMPRODUCT(IFERROR(INDEX(statusTbl,MATCH(Status,statusTbl[Status],0),2),0),
IFERROR(INDEX(priorityTbl,MATCH(Priority,priorityTbl[Priority],0),2),0))
If you want to change the values you assign to the different Priority/Status items, you merely change them in the table.
You could also add new rows to the tables, if that is appropriate.
Note that I did not bother adding to the tables rows where the value might be zero, but you could if you wanted to.
Consider this example. There are two columns one called grade with a number 1-10 and another called status that says pass or fail. Originally, any number 1-6 resulted in fail and everything from 7-10 said pass.
Grade | Status
1 | Fail
2 | Fail
3 | Fail
4 | Fail
5 | Fail
6 | Fail
7 | Pass
8 | Pass
9 | Pass
10 | Pass
Now I lowered the passing grade to a 6. I want to replace every fail in the status column with pass if it has a grade of 6. How would I do this using an if statement in Excel?
It sounds as if you're looking for a simple IF statement for your worksheet. If so, try this:
=IF(A2<6,"Fail","Pass")
Take this formula and drag it down your range, adjusting where necessary.
Below are some screens I threw together to show the formula a bit better.
This is how I assumed you had your original worksheet set up:
And this is how I set it up based on your request:
I'm trying to plot some data (standard curves for analytical chemistry) where the x axis is the mass of a compound I added to a solution, and the y axis is the signal recorded from an instrument (peak height on a mass spectrometer). I'd like Tableau to color code the data by compound (compound A, compound B, compound C, etc.), so that I'd wind up with a graph that looks something like this:
The original structure of my data was like this:
SampleID | Mass A | Mass B | ... | Signal A | Signal B | ...
standard 0 | 0| 0| ... | 0| 0| ...
standard 5 | 2.535| 2.555| ... | 0.494| 1.240| ...
standard 25| 12.675| 12.775| ... | 2.426| 7.235| ...
I know how to make graphs one compound at a time with these original data, but for the purposes of other analyses I'm doing with these data and because I want multiple compounds on the same graph, I've pivotted them so that the structure is now like this:
SampleID | Compound | Parameter | Value
standard 0 | A | Mass | 0
standard 0 | A | Signal | 0
standard 5 | A | Mass | 2.535
etc.
How do I make a graph where the mass is on the x axis, the signal is on the y axis, and the points are colored by compound? I don't see a good way to do it when my data are in this format. I've tried making new calculated variables where the value = NULL if the parameter is not equal to "Mass" and another calculated variable where the value = NULL if the parameter is not equal to "Signal" and then putting those pills on the columns and rows, but that's not working. Is there a way to do this in Tableau with data structured like this pivotted form?
Alternatively, is there a way to spread my pivotted data so that the new structure is like this:
SampleID | Compound | Mass | Signal
standard 0 | A | 0| 0
standard 5 | A | 2.535| 0.494
standard 25| A | 12.675| 2.426
standard 0 | B | 0| 0
etc.
and would that work better?
(For R users, that last bit would be the equivalent of the tidyr package gather and spread functions.)
To make the second structure appear like the third, add a calculated field called Mass defined as if Parameter = "Mass" then Value end. Do the same for Signal.
You can then hide the fields Parameter and Value if you like, and work with Mass and Value instead.
Put AVG(Mass) on the Columns Shelf and AVG(Signal) on the Rows shelf -- AVG, not ATTR. Then finally, put [Sample Id] on detail.
If I had to deal with this, I'd prefer to pre-process the data so that it has the format "SampleID | Compound | Mass | Signal", that would make Tableau chart straightforward.
I think there's a way to achieve the same with the data structure you have, but it's more tricky. So, if I understand correctly, you have the data it this form:
SampleId Compound Parameter Value
standard 5 A Mass 2.535
standard 5 A Signal 0.494
standard 5 B Mass 2.555
standard 5 B Signal 1.24
standard 25 A Mass 12.675
standard 25 A Signal 2.426
standard 25 B Mass 12.775
standard 25 B Signal 7.235
1) You can create calculated fields for Mass and Signal using level of detail expressions, that exclude the Parameter granularity:
Mass
{exclude [Parameter] : min(if [Parameter] = 'Mass' then [Value] else NULL end)}
Signal
{exclude [Parameter] : min(if [Parameter] = 'Signal' then [Value] else NULL end)}
That will "collapse" nulls in case Parameter is not included in the view.
2) Using the Scatter Plot visualization, you can pull Mass to columns and Signal to rows, add Compound to Color pane and SampleId to Detail pane. The plot will look like this:
having a tough time figuring out how to model the expected product behavior.
Basically, the customer's inventory is managed along products and skus.
A product has many skus, but a single sku accounts for several product attributes.
Let me give an example.
Let's say i'm selling you a shirt. "Shirt" is the product with some product ID. If it comes in small, medium, large, then each of those sizes would be associated with a sku #.
easy enough so far, but if the shirt also comes in multiple colors, let's say red, yellow, and green, then there will be nine skus (red/small, red/medium, red/large, yellow/small, and so on).
Add to that the challenge that the types of attributes can be different for different products. A shirt might have sizes and colors, a handbag might have different handle styles or patterns, and I won't know ahead of time, these are things that the customer needs to be able to input in an adhoc fashion.
Any ideas on how to approach this from a DDD perspective? I"ve been baking my noodle on it for a few days now.
Thanks.
First of all you have to regard each sku as a single product attribute and not combine them. If a product can have a color and a size, these are two distinct attributes, not one (as in red/small, red/medium, etc). Suppose a product has five attributes, each with 4 possible values. You would then have 4^5=1024 skus. This quickly becomes a maintenance nightmare.
So, the first two objects in your domain model should be ProductDefinition and Attribute. The reason I choose ProductDefinition as a name and not Product is that this is just a label for some product type, a shirt for example. It is not yet a small yellow shirt.
Attributes can have possible values, so this makes for a third domain object: AttributeValue. The relation between Attribute and AttributeValue is 1:n. An attribute has multiple values, a value only belongs to one attribute.
Note that AttributeValue contains all possible values for an attribute, not the actual value for a single product. This actual value becomes a relation between ProductDefinition, Attribute and AttributeValue: ProductAttributeValue. Up for the shirt example in a database model:
ProductDefinition Attribute AttributeValue
1 | Shirt 1 | Color 1 | 1 | Red
2 | Size 2 | 1 | Yellow
3 | 1 | Green
4 | 2 | Small
5 | 2 | Medium
6 | 2 | Large
We have now modeled one product definition, two attributes and three attribute values per attribute. Suppose now we want to model three shirts: a small red one, a small green one and a large yellow one. This results in the following ProductAttributeValue content (ProductId, ProductDefinitionId, AttributeId, AttributeValueId):
ProductAttributeValue
1 | 1 | 1 | 1
1 | 1 | 2 | 4
2 | 1 | 1 | 3
2 | 1 | 2 | 4
3 | 1 | 1 | 2
3 | 1 | 2 | 2
We did a system like this..
ProductDefinition
has Type (Shirt, Handbag)
has many ProductFieldDefinition
ProductFieldDefinition
has Type (Color, size, pattern)
Product
has ProductDefinition
has SKU
has many ProductField
has ProductFieldDefinition
has Value
The one thing I would change in our system is I would use a Document Database to store everything but in our case the graph actually went much deeper with each level having it's own fields.