-
-
Notifications
You must be signed in to change notification settings - Fork 546
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
twelve-days: Implement canonical-data.json #954
Conversation
I'm not sure about my implementation of canonical-data.json. The problem is that a lot of language tracks test every single line of the song - like 1, 2, 3 and so on till 12. I don't understand the reason behind it - it looks redundant to me. So, I think it's important to test the first and the last lines (checking the offset if some array-like data structure is used). Then, we check that all other parts of the song are there when we will run tests for intervals (for example, from first to third line). So, I don't really know what should be a priority - sticking to test cases that already are in many language tracks, or creating a suite of essential tests. |
With only 12 items it doesn't seem unreasonable to test every verse individually. |
Added test cases for every verse and changed their descriptions accordingly |
"version": "1.0.0", | ||
"cases": [ | ||
{ | ||
"description": "returns verse number 1", |
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.
I'd like to see more descriptive descriptions. This does not tell me anything that cannot be automatically generated from the input.
How about:
"first day a partridge in a pair tree"
"second day two turtle doves"
etc.
Or something similar.
{ | ||
"description": "finds multiple verses, which are a fragment of the song", | ||
"property": "verses", | ||
"input": [1, 3], |
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 is no test for verses that doesn't start at 1
what should happen in that case?
6f48f6a
to
e16ce00
Compare
Thanks @Insti, I've changed test descriptions and added test for interval from the middle of the song (4-6). Also changed interval test description accordingly. I have also rebased commits into one. |
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.
it seems to me that for the verse
tests, instead of having "input": [1],
it can just be "input": 1,
- it will never be the case that the input should contain more than one verse number, so might as well not use an array.
input
also seems unnecessary for sing
.
ac6f0ed
to
2f85bb6
Compare
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.
Nice.
I am wondering whether the trailing newlines on all expected outputs are necessary. Naively I might assume they aren't, but maybe there is something I don't know.
After this, I think I have said all I need to say. I haven't explicitly checked that all the expected values are correct, so I leave that to others (in other words, please don't wait for my approval before merging)
Thank you @petertseng |
I agree. It makes sense for the verses to be separated by newlines, but for an individual verse it doesn't IMHO. Maybe this is the point where we should remove those extra newlines? |
Okay, I a bit confused now, so, just to be clear - we are talking about last newline symbol at the end of each verse/block of verses, right? |
"description": "first day a partridge in a pear tree", | ||
"property": "verse", | ||
"input": 1, | ||
"expected": "On the first day of Christmas my true love gave to me, a Partridge in a Pear Tree.\n" |
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.
I believe the suggestion is that this line should not have the \n
at the end.
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.
Correct
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.
Removed trailing newline for single verse tests
"description": "finds multiple verses, which are a fragment from the beggining of the song", | ||
"property": "verses", | ||
"input": [1, 3], | ||
"expected": "On the first day of Christmas my true love gave to me, a Partridge in a Pear Tree.\n\nOn the second day of Christmas my true love gave to me, two Turtle Doves, and a Partridge in a Pear Tree.\n\nOn the third day of Christmas my true love gave to me, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.\n" |
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.
But whenever there are multiple verses they should be separated by \n\n
But no trailing newline. Maybe the trailing single newline should be there.
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.
But it only makes sense in the context of multiple verses, so why add it to a single verse?
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.
Maybe the trailing single newline should be there.
In this case I am wondering about how many newlines should be at the end of the completed verses
string. 0, 1 or 2? Currently there is 1.
I still agree there should be 0 at the end of each individual verse.
And that the joined verses should be separated by newlines.
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.
I would expect the following to hold:
- A single verse would have no newline at the end
- Verses (more than one) are separated by an empty line
- Verses don't have trailing newlines (so that means 0)
e5ada1f
to
e0a528e
Compare
Fixed |
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.
Looks great 👍
Do you have an automated checker for this exercise @petertseng ? |
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.
Do you have an automated checker for this exercise @petertseng
Nope.
{ | ||
"description": "finds multiple verses, which are a fragment from the beggining of the song", | ||
"property": "verses", | ||
"input": [1, 3], |
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.
hmm, sorry to swoop in with another thing again, but I just remembered... what about assigning meaning to the two elements of this array? See how beer song
does it at https://github.com/exercism/problem-specifications/blob/master/exercises/beer-song/canonical-data.json#L54-L55 . Any desire to do the same here?
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.
Added two elements instead of one array; named them beginning
and end
respectively. Not sure if it will be a good idea to split all cases into two groups, like "beer-song" does (for single and multiple verse test cases).
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.
Should beginning
and end
be subkeys of input?
"input": {"beginning": 1, "end": 3}
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.
Should it? Wouldn't it be confused with some object or map data structure?
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.
Should
beginning
andend
be subkeys of input?
That would be an interesting change to make for the JSON files all around. Then, instead of having to vary the input keys per exercise, test generators would know that all inputs can be found in "input"
. That could be a useful change for the schema! I think the track maintainer who wishes that to happen for all JSON files should make the issue requesting it.
4f41e70
to
3675be6
Compare
"end": 3, | ||
"expected": "On the first day of Christmas my true love gave to me, a Partridge in a Pear Tree.\n\nOn the second day of Christmas my true love gave to me, two Turtle Doves, and a Partridge in a Pear Tree.\n\nOn the third day of Christmas my true love gave to me, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree." | ||
}, | ||
|
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.
Line 84 should be removed.
{ | ||
"description": "twelfth day twelve drummers drumming", | ||
"property": "verse", | ||
"input": 12, |
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.
Instead of "input"
how about "number"
since it is the verse number being asked for.
If you would like to make this more |
3675be6
to
cf30929
Compare
Thanks @rpottsoh |
OK, guess that wasn't so much to write. require 'json'
require_relative '../../verify'
DAYS = {
twelfth: 'twelve Drummers Drumming',
eleventh: 'eleven Pipers Piping',
tenth: 'ten Lords-a-Leaping',
ninth: 'nine Ladies Dancing',
eighth: 'eight Maids-a-Milking',
seventh: 'seven Swans-a-Swimming',
sixth: 'six Geese-a-Laying',
fifth: 'five Gold Rings',
fourth: 'four Calling Birds',
third: 'three French Hens',
second: 'two Turtle Doves',
first: 'a Partridge in a Pear Tree',
}.each_value(&:freeze).freeze
def list(things)
things.size == 1 ? things[0] : (things[0...-1] << "and #{things[-1]}").join(', ')
end
def verse(n)
ordinal = DAYS.keys[-n]
gifts = DAYS.values.last(n)
"On the #{ordinal} day of Christmas my true love gave to me, #{list(gifts)}."
end
def verses(a, b)
(a..b).map { |n| verse(n) }.join("\n\n")
end
json = JSON.parse(File.read(File.join(__dir__, 'canonical-data.json')))
raise "There should be exactly two cases, not #{json['cases'].size}" if json['cases'].size != 2
verify(json['cases'][0]['cases'], property: 'verse') { |c|
verse(c['number'])
}
subcases = by_property(json['cases'][1]['cases'], %w(verses sing))
verify(subcases['verses'], property: 'verses') { |c|
verses(c['beginning'], c['end'])
}
verify(subcases['sing'], property: 'sing') { |c|
verses(1, DAYS.size)
} As written, it's fine. Note that it may be a bit strange that both |
Should |
Looking at the description and the policy that we should not be testing intermediate values it would seem that there should only be one test for the complete song. (Sorry I've only just noticed this @alpakhomov ) The solution may be to update the description to add the requirement that verse ranges are also required, otherwise the tests will be passable by a hardcoded string, which seems like it would not be a "good" exercise. The interface could then be, sing(x,y) where x <= y. and we don't need 3 different methods. Thoughts? |
cf30929
to
336aaf7
Compare
I changed properties and descriptions of tests in the |
Hi @alpakhomov, are you willing to make some more changes to this to match what we're planning on doing to food-chain in #973
|
336aaf7
to
6f995b2
Compare
Changed property and parameter names, everything else is the same |
Great work @alpakhomov ! What I was wondering, is if we should encoding the expected value as an array of strings instead of a single string, similar to what happens in the food-chain canonical data? My personal preference would be to use an array. @Insti, what are your thoughts? |
I have no strong opinion, an array of strings seems fine, so long as there is a comment about it for the test implementer: https://github.com/exercism/problem-specifications/blob/master/exercises/food-chain/canonical-data.json#L4-L7 |
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.
Convert the multi-line expectations into an array of strings.
{ | ||
"description": "first day a partridge in a pear tree", | ||
"property": "recite", | ||
"start verse": 1, |
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.
We have now come up with an updated format, which requires the properties to be lowerCamelCase (see #983). Could you update the property to startVerse
? And do the same for the other "start verse" properties?
"description": "first day a partridge in a pear tree", | ||
"property": "recite", | ||
"start verse": 1, | ||
"end verse": 1, |
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.
We have now come up with an updated format, which requires the properties to be lowerCamelCase (see #983). Could you update the property to endVerse
? And do the same for the other "end verse" properties?
"property": "recite", | ||
"start verse": 2, | ||
"end verse": 2, | ||
"expected": "On the second day of Christmas my true love gave to me, two Turtle Doves, and a Partridge in a Pear Tree." |
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.
@alpakhomov Sorry about the churn in the changing requirements! It has taken us a little while to come up with uniform specifications, but the final result is in #983 and it should now be stable. |
6f995b2
to
201be91
Compare
Renamed parameters with camelCase, changed all expected values to arrays (even single line ones), added comment about expected values same as here https://github.com/exercism/problem-specifications/blob/master/exercises/food-chain/canonical-data.json#L4-L7 |
I think this is ready to merge. @Insti, do you agree? |
Yes it looks good to me. |
Merged! Thanks a lot @alpakhomov! |
Thanks for all your work on this @alpakhomov and your patience with the constantly changing requirements ❤️ |
Resolves #590 // m-a-age