I'm practicing event-storming, with sticky notes and stuffs.
But one thing is missing: command validation (rules to be satisfied for a command to be accepted / succeed).
How to make it visible in the whiteboard? (not just as comments sprinkled here and there). Event-storming only mentions "events" (yellow), "command" (blue), "aggregate" (pale yellow), etc. I don't see "command validation" as first-class citizen.
Any thoughts?
I would consider command validation as policies in event storming. Those are business rules that must be satisfied for a command to be accepted.
They will go on pink "policy" sticky note - https://eventnotes.io/pdf/cheatsheet-big-picture-exploration.pdf
I consider policies as:
Control how the action plays out
Business rules
Decisions
When an event occurs, you apply policy and decide what the next action is
Reactive logic
External decision
Time based
Trigger based
Reacts on events
Triggers commands
Often at domain boundary
I had this same trouble and worked through it like this....
First understand there are different types of validation. What is the type of validation you want to do?
Do you want to validate a model to ensure the order address is correctly formatted? This would only extend to "schematic" validation and could be done synchronously as part of your command, and would be what I would call Command Validation. I would make a note somewhere with the language as this will be taken through to build the contract.
Do you want to validate that "if there isn't enough stock to complete the order the order should fail"? It is not the commands responsibility to validate business logic, it is the aggregate; and I would call this Domain Validation. I use negative events to indicate some form of validation has taken place in the aggregate.
I hope this helps
Related
I am trying to convert Selenium test to Gherkin. Is there way to implement if statements in Gherkin?
Example : assume the code is written in the below format. I am just writing description as below. Please understand the part after double slash is the actual Selenium code:
// launch the application
// login to application
// navigate to page
String str;
if(str== "XYZ")
{
// verify title
}
//verify text field 1
//verify test field 2
//verify select box
For this I am trying to write code in Gherkin as follows
Given user launches the application
When user login with valid credentials
and navigate to required page
When String str is "XYZ"
Then verify title
And verify text field 1
And verify test field 2
And verify select box
but this code is incorrect because if the str is not equal to "XYZ" we want that title should not be verified but other verification like text field1,2 and select box should be verified.
You don't implement if in Gherkin.
Gherkin is about communication and those you want to communicate with, non coders, don't know what an if statement is. They don't care either.
The solution? Two scenarios to cover both cases.
Ideally, this level of detail would not be in your Gherkin scenario. The best approach is describe business use cases, not low level details. This is what Gherkin is designed for: communicating with non-technical stakeholders so that you can work out if you are building the right thing in the first place. Here is what I would write:
Given the user is logged in
And the user is on the required page
When they enter data that requires the optional fields to be validated
And they enter invalid data in the optional fields
Then the form shows an error on the optional fields
The low level details don't matter (that the string is specifically "XYZ" or that it is the title field is not important), so these should be hidden in the step definition and/or unit tests.
In order to continue to check the other fields, you can just add another step after this:
When they enter invalid data in all of the other fields
Then each other field has an error message attached to it.
Again, there is no need to specify the actual fields, or separate them into their own steps. The idea is to express the high level business value of the scenario, i.e. that the form is validated when it should be.
The advantage to keeping things high level is that when the form changes (as it eventually probably will), then this scenario can remain untouched. Which is correct as the business case is the same: it should validate when it's supposed to. All the changes will be in the step definitions. This means that there is no reason to have another discussion with your stakeholders about whether your scenarios are still testing the right thing.
You can write the scenario, somewhat like this:
Given the user launches the application
When user login with valid credentials
And navigates to required page
Then he should see the page datails
Inside the Then step you manage all the logic.
Then(/^he should see the page details$/) do
if condition
...
else
...
end
end
Gherkin is not a programming language to use if or else conditions. It is a part of BDD framework, that is implemented, to make the stakeholders and other non technical resources understand what the test process is about. Hence, it is always recommended, you keep the gherkin as simple and as generic as possible.
Strictly speaking you should create an alternative statement along the lines of:
Given user launches the application
When user login with valid credentials
and navigate to required page
When String str is NOT "XYZ"
I have created the below diagram and I wanted to know if the diagram that I have done is correct.
The below diagram is based on an android application. When the application loads the user is given 3 button to select add, update and help. On click on add button the user is given an option to add a new user or add a new item. When he select either of the options he enters the required data once the data is entered the system check if all the values are entered correctly and then finally saved. The same process is applied for update.
Your diagram misses an entry point. Though it's rather obvious that the top action is the start, only the entry point is the one indicating the beginning.
You can omit most of the diamonds and directly transfer via a guard from actions. So your conditions should be guards and written as [Yes] or [No]. The top most action (and quite some others) is(/are) indeed what should be written inside (or aside) the diamond below.
An excerpt for an update could look like this:
Finally Values added does not look like an action but rather as state. It should be omitted. Alternatively use differently named end flows.
So far for the formal points. But as #eyp said: it's a good one and one can understand what you tried to express. The above is just for the picky teachers.
It's a good one but it lacks some detail in the diamonds. You should write besides the diamon the question before choosing the next setp to do.
For example in the diamond after Check update value you may write is valid? or another question that clarifies more the business logic.
I understand the difference between imperative and declarative cucumber steps, but I have not seen any real world examples of this. I always feel like my feature files are becoming too verbose.
It seems like there would need to be a cucumber feature for each step in the life cycle:
foobars/list_foobars.feature
foobars/create_foobar.feature
foobars/view_foobar.feature
foobars/edit_foobar.feature
foobars/delete_foobar.feature
In the create feature alone, it seems like you would want to list out the fields that can be entered, which ones are required, what happens when you enter invalid data, etc. I don't know of a declarative way to do this. Of course in subsequent features, you would just say Given a foobar exists rather than going through all the steps to create one.
How detailed do you go when describing your application's behavior? Can you provide some examples of feature files that you feel are acceptably complete?
I like to keep cucumber tests human readable, so assuming we have a story for editing a foobar with invalid data, I'd want a scenario like:
# foobars/edit_foobar.feature
Feature: As a user, I want to edit a Foobar, so I can Baz
Scenario: Validation Errors
Given I am logged in as a user
And a foobar exists
And I edit the foobar with invalid data
Then I should see validation errors
I think that captures what we want out of the story, without having to deal with all the details of which fields to edit, what buttons to submit, etc. It doesn't test all the possible cases, but those should really be tested via unit tests (model tests that the validations are set, and controller tests that the flash messages are set or request tests that the errors are being served).
The other scenarios are similar:
Scenario: Successful Edit
Given I am logged in as a user
And a foobar exists
And I edit the foobar with valid data
Then I should see the valid data
Some people will want to specify the valid data as part of the test itself, but I personally prefer to delegate these to the step definitions in order to keep the scenarios clean. You just need one example to make sure the golden case works, because again this isn't the appropriate place to test that all the form fields work (and it will become a maintenance headache if you do specify every single field).
I am thinking maybe not test this at all using Cucumber, instead just make a comment in the Feature section.
Alternatively maybe one can do something like this:
# categories.feature
Scenario: Manage categories
Given I want to manage categories
When I <crud_type> a category
Then I should be taken to the listing page
Examples:
| crud_type |
| create |
| edit |
| delete |
Scenario: View category
Given I want to view a particular category
When I click on a category in the category list
Then I should see that category's view page
I have come across several examples of dependencies e.g. include, extend however it is utterly confusing. One example dictates that include should be in the direction of;
user profile --> login
Whilst extends should be in the direction of;
validate credit card <-- print receipt.
Whereas required should in the direction of; For the life of me I don't get why this can't be an include
place order --> create account
Also does it matter how these are constructed i.e.
user profile --> login (include)
**vs**
validate credit card (extend)
^
|
|
|
print receipt
I am not sure I fully understand every part of your questions, but here we go:
An include goes from the including to the included. It denotes a mandatory sub part of the use case :
including -----------> included
<<include>>
Extend is the same than include, but the sub part is not mandatory. And unfortunately, the arrow is the other way around. Which seems to puzzle you a lot.
including <----------- optionnally included
<<extend>>
When you speak about required, I suppose it is an anonymous dashed arrow? In fact, such a dependency can be written for anything, use case or not. It is not that usual for use cases, but it could mean that a use case has another as a prerequisite. Difference with include is that it is not a sub part. In this case, it is drawn this way.
requiring -----------> required
In your example, it seems that to place an order, you must have created an account (logical indeed). But account creation is not a sub part of order placing, so it is not an include.
As for your last question, are you talking about vertical/horizontal? If so, it does not matter in UML. In fact, there is no rule about positioning, the only rule is to remain clear.
I am designing a workflow that uses the status reason to route cases to a variety of queues within our organisation.
In order to enforce the process within the workflow (and to reduce the number of status reasons the user needs to select from), I would like to restrict which status reasons can be selected based upon the case's current status reason. We have 12 status reasons.
E.g. I would like to ensure that a if a case is in a "Ready for Report Creation" status reason, users can only set the status reason to "Cancelled", "On Hold" or "Draft Report Completed" - but they should not be able to set the status reason to "Report Approved".
I have given some thought to the issue and the current solution I am considering is to:
Hide the status reason field on the case.
Create a CRM dialog process, which provides the user with the relevant status reasons to choose from, based upon the current status reason for the case.
Whilst this solution is effective, a lot of configuration is required as a page is required for each status reason - within the CRM dialog process.
Does anyone have any suggestions as to less unwieldy solution to this problem?
NOTE: This is an on-premise installation so we have complete flexibility w.r.t. types of solution we can deploy.
Couple of ways to do this.
A dialog would certainly give you a codeless option.
If you are happy to use JavaScript, you could add & remove options dynamically using functions like adoption, clearOptions and removeOption from Xrm.Page.ui Control Methods. Which would give a more fluid user experience.
If you want to enforce the business rules you could also add a plugin which throws exceptions when the wrong status is set, to prevent any data imports or other processes from setting the value incorrectly.