-
-
Notifications
You must be signed in to change notification settings - Fork 22
[DotNet] Fix generation of classes that accept optional lists as constructor arguments #249
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
bf1407e
fc7edd5
b099347
fc7ee47
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,7 +45,7 @@ string id | |
| RequireNonNull<string>(description, "Description", "Background.Description cannot be null"); | ||
| this.Description = description; | ||
| RequireNonNull<List<Step>>(steps, "Steps", "Background.Steps cannot be null"); | ||
| this.Steps = new List<Step>(steps); | ||
| this.Steps = steps == null ? new List<Step>() : new List<Step>(steps); | ||
|
||
| RequireNonNull<string>(id, "Id", "Background.Id cannot be null"); | ||
| this.Id = id; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -52,8 +52,8 @@ List<StepMatchArgumentsList> stepMatchArgumentsLists | |||||
| RequireNonNull<string>(id, "Id", "TestStep.Id cannot be null"); | ||||||
| this.Id = id; | ||||||
| this.PickleStepId = pickleStepId; | ||||||
| this.StepDefinitionIds = new List<string>(stepDefinitionIds); | ||||||
| this.StepMatchArgumentsLists = new List<StepMatchArgumentsList>(stepMatchArgumentsLists); | ||||||
| this.StepDefinitionIds = stepDefinitionIds == null ? new List<string>() : new List<string>(stepDefinitionIds); | ||||||
|
||||||
| this.StepDefinitionIds = stepDefinitionIds == null ? new List<string>() : new List<string>(stepDefinitionIds); | |
| this.StepDefinitionIds = stepDefinitionIds == null ? null : new List<string>(stepDefinitionIds); |
The field is not required, so it can be null. When serializing, if configured correctly, this will result in the omission of the field. And so it would be strange if non-required value that wasn't present suddenly became an empty list after serialisation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In principle, I agree with you, purely optional elements should be null and not emitted when serialized.
I'm curious then about these lines in the Hooks example in the CCK:
{"testCase":{"id":"33","pickleId":"20","testSteps":[{"hookId":"0","id":"29"},{"hookId":"1","id":"30"},{"id":"31","pickleStepId":"19","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"4","id":"32"}]}}
{"testCase":{"id":"38","pickleId":"22","testSteps":[{"hookId":"0","id":"34"},{"hookId":"1","id":"35"},{"id":"36","pickleStepId":"21","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"4","id":"37"}]}}
{"testCase":{"id":"43","pickleId":"24","testSteps":[{"hookId":"0","id":"39"},{"hookId":"1","id":"40"},{"id":"41","pickleStepId":"23","stepDefinitionIds":[],"stepMatchArgumentsLists":[]},{"hookId":"4","id":"42"}]}}
In the first two lines, the third step of each test case is matched with a StepDefinition; each of those stepDefinitions accept no parameters. So why are the stepMatchArgumentsLists and stepMatchArguments properties being serialized as empty lists? Why not omit them altogether? (They are optional according to the schema).
Likewise in the third example (the test case does not bind to any step definition (aka, pending). Why is the StepDefinitionIds array getting serialized when it is empty?
I will try out your proposal and see how well it works with Reqnroll.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A TestStep is either a PickleTestStep or a HookTestStep.
- When a
PickleTestStepthen theid,pickleStepId,stepDefinitionIdsandstepMatchArgumentsListsare required. - When a
HookTestStepthen theidandhookIdare required.
So in the union of these, only the id is required.
There are now better ways to express this in a json schemas but either we didn't have those at the time, or they didn't quite work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oof. That makes a general solution almost impossible.
If the template were to deserialize missing optional lists as null then they won't round-trip correctly. (Nor would it round-trip correctly with the code as it exists or with what I had proposed)
I'll consider inserting a patch up phase in the Serializer helper class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does it make round tripping correctly impossible? Not including null values when serializing and not replacing absent/null values with empty list during deserialisation is a successful round trip.
Or do you mean with the current implementation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, OK, not impossible.
Under good conditions, the round-trip would be successful.
Under the principle of being forgiving of bad input and strict on output; if the input json string (for a Pickle TestStep) were to omit the stepDefinitionIds instead of representing it as an empty array, then this code would set the StepDefinitionIds property to null, and render it back out during serialization as null (rather than the required empty array).
Are those edge cases something that we should be guarding against?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There might be a use-case for it, but it would be somewhat out of scope for this PR.
In this example, an error correction to an empty list would be context sensitive. The correct solution would depend on whether we are dealing with a PickleTestStep or a HookTestStep.
Given that sort of complexity, probably best discussed separately, if at all.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spotted this after merging. Changes should be listed as one of
Added,Changed, ect. I'll fix it on main.