generators: Auto extract cases#568
Conversation
| Files::GeneratorCases.filename(exercise_name) | ||
| end | ||
|
|
||
| def test_cases |
There was a problem hiding this comment.
There is a LOT of untested logic here. That scares me.
| end | ||
|
|
||
| def test_cases_proc? | ||
| Object.const_defined?(test_cases_procname) |
There was a problem hiding this comment.
Use the method you already have: test_cases_proc.exists?
There was a problem hiding this comment.
test_cases_proc returns NameError if the constant is not defined. I dislike rescuing an error in this situation, but would prefer to check to see if it is there.
There was a problem hiding this comment.
It was desirable before, for the whole thing to blow up if the test case class did not exist. Since that's no longer the case it suggests to me that test_cases_proc needs changing to something like:
def test_cases_proc
Object.const_get(test_cases_procname) if Object.const_defined?(test_cases_procname)
end
(This may be moot due to upcoming object extraction.)
|
|
||
| def test_class_name | ||
| assert_equal 'TwoParterCase', GeneratorCases.class_name('two-parter') | ||
| end |
|
|
||
| def proc_name(exercise_name) | ||
| filename(exercise_name).split('_').map(&:capitalize).join | ||
| "#{class_name(exercise_name)}s" |
There was a problem hiding this comment.
If you're just adding an 's' do class_name(exercise_name) + 's'
|
I'd like to see an example of how |
| test_cases_proc.call(canonical_data.to_s) | ||
| else | ||
| test_cases_with_index | ||
| end |
There was a problem hiding this comment.
There's another object hiding in here.
Replace all this with:
test_cases_foobar.call(canonical_data.to_s)
Then work out what test_cases_foobar is.
There was a problem hiding this comment.
This will also help solve your (my) "bunch of untested private methods" problem.
There was a problem hiding this comment.
💯 Win, win, win. I'll refactor and dig that object out tomorrow.
|
|
| end | ||
|
|
||
| def test_case_class | ||
| Object.const_get(Files::GeneratorCases.class_name(exercise_name)) |
There was a problem hiding this comment.
@Insti here is where class_name is used.
There was a problem hiding this comment.
So proc_name is never used externally and should be private?
I read the comment above.
|
Refactoring to split apart the adapter and the two solutions |
| simple_canonical_data | ||
| end | ||
|
|
||
| def complex_canonical_data |
There was a problem hiding this comment.
These (simple|complex) can live in /fixtures somewhere.
There was a problem hiding this comment.
We discussed this in gitter and have decided to try a data section at the end of the test file.
The main thing is removing the big heredoc from the middle of the test file.
|
|
||
| class CaseValuesTest < Minitest::Test | ||
| def setup | ||
| $LOAD_PATH.unshift 'test/fixtures/xruby/lib' |
There was a problem hiding this comment.
Modifying the load path for every test should not be necessary.
But there might be something else to do so that everything still works.
There was a problem hiding this comment.
I was following the existing pattern.
There was a problem hiding this comment.
I probably should fix that then 😊
| end | ||
|
|
||
| def simple_canonical_data | ||
| simple_canonical_data = Minitest::Mock.new |
There was a problem hiding this comment.
Why is this a Mock?
Nevermind.
| complex_canonical_data = Minitest::Mock.new | ||
| complex_canonical_data.expect( | ||
| :to_s, | ||
| <<-TEXT |
There was a problem hiding this comment.
Were you going to move this data out of the tests?
There was a problem hiding this comment.
They're at the bottom of the file now.
Where I'd really like to put these is in a module I could include.
There was a problem hiding this comment.
In which case why not use a fixture?
How is a module any different, or even preferable when the data should be non-executable?
There was a problem hiding this comment.
A module can easily be included in multiple places, but (may be/is ?) easier to be surgical than a fixture.
I guess the question is, what are you suggesting? That I create fixtures for each of these cases, in which case I will end up duplicating data or reusing fixtures across tests, neither of which is desirable.
While data is non-executable, being able to manipulate the data via code makes the test suite far more manageable.
| @@ -0,0 +1,116 @@ | |||
| require_relative '../test_helper' | |||
There was a problem hiding this comment.
case_values_auto_extractor_test.rb has too many _auto_extractors in the filename
| $LOAD_PATH.delete 'test/fixtures/xruby/lib' | ||
| end | ||
| end | ||
|
|
There was a problem hiding this comment.
An unnecessary blank line change has snuck in.
| $LOAD_PATH.unshift 'test/fixtures/xruby/lib' | ||
| end | ||
|
|
||
| def test_simple_auto_extraction |
There was a problem hiding this comment.
I believe this test is redundant.
Just load the alpha_cases file direcly, we know where it is.
test/fixtures/metadata/exercises/alpha/canonical-data.json We are the only user of this fixture data.
Renamed 'gamma' to 'complex'.
Add test that template_values loads problem cases Remove commented out code. Make everything that loads AlphaCase(s) clean up after itself. Undefine AlphaCase(s) during teardown. Remove redundant setup. Check for both classes. Add tests for class based test generation squash Remove TODO comment
9a14c4d to
45511ff
Compare
all generators converted to use auto extraction in exercism#567
(We're not making use of it yet, but now it is there we can.)
Refactor Extractor
Motivation and Context
While working on #566, I noticed that a number of the existing generators would not run because the loop which extracts cases from the data did not match the current structure. I also noticed a lot of consistency in the loops for both failing and successful generators. Automatically extracting cases from the JSON feels like a big win.
Description
Added
Generator::CaseValues(inlib/generator/case_values.rb, which extracts the cases from the canonical data. It uses a custom extractor if such an extractor exists, otherwise it extracts the cases automagically.How Has This Been Tested?
Generator::CaseValuesfor both custom extractor and not custom extractor and for both simple and complex canonical data.Generator::Files::GeneratorCases.Types of changes
No breaking changes.
New feature: auto extraction of cases.
References and Closures
Checklist:
My change relies on a pending issue/pull request