-
Notifications
You must be signed in to change notification settings - Fork 5
Test: test for copy_examples
#60
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
Conversation
|
@sbillinge ready for review I recognize that the code for this test is somewhat particular because of the temp dir structures we are testing, but I think it should be robust to the UCs listed above. I wanted to reuse the same temp dir that we created for the other test so that this test casts a broader net of cases it can check. However, we could simplify this test if you think this might be a bit overkill. |
sbillinge
left a comment
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 reviewed the comments but not the code yet. I can do that later but I don't see the function signature and am on my phone so will do it later
|
@sbillinge So I dont override these changes before your review, here's a simpler test i wrote. |
sbillinge
left a comment
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.
Please see content
src/diffpy/cmi/cli.py
Outdated
| examples_dict : dict | ||
| Dictionary mapping pack name -> list of (example, path) tuples. | ||
| user_input : list of str | ||
| List of user-specified pack(s) or example(s) to copy. |
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.
please review. Think this would be useful for parsing examples_dict
|
@sbillinge I changed the |
|
@sbillinge Ready for review. I updated the test such that it takes the actual cli command |
|
for the tests I like the new test, it is cleaner, but my suggestion would be to:
|
|
@sbillinge ready for review. I pasted the new tmp dir structure here #54 (comment) Note, still need to update behavior comments, but will do that after lunch! |
tests/test_cli.py
Outdated
| assert dest_file.exists() | ||
| else: | ||
| empty_dir = list(target_dir.rglob("*")) | ||
| assert not empty_dir, f"Expected nothing, but found: {empty_dir}" |
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.
Because we have expected paths that are empty (ie case1 and case4), these cases pass even though copy_examples isnt built. This will fail if copy_examples copies anything into the target directory.
tests/test_cli.py::test_copy_examples[case1-user_inputs0-expected0-None] PASSED [ 10%]
tests/test_cli.py::test_copy_examples[case1-user_inputs0-expected0-user_target] PASSED [ 20%]
tests/test_cli.py::test_copy_examples[case2-user_inputs1-expected1-None] FAILED [ 30%]
tests/test_cli.py::test_copy_examples[case2-user_inputs1-expected1-user_target] FAILED [ 40%]
tests/test_cli.py::test_copy_examples[case3-user_inputs2-expected2-None] FAILED [ 50%]
tests/test_cli.py::test_copy_examples[case3-user_inputs2-expected2-user_target] FAILED [ 60%]
tests/test_cli.py::test_copy_examples[case4-user_inputs3-expected3-None] PASSED [ 70%]
tests/test_cli.py::test_copy_examples[case4-user_inputs3-expected3-user_target] PASSED [ 80%]
tests/test_cli.py::test_copy_examples[case5-user_inputs4-expected4-None] FAILED [ 90%]
tests/test_cli.py::test_copy_examples[case5-user_inputs4-expected4-user_target] FAILED [100%]
sbillinge
left a comment
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.
the cases are all good now, but this testing is all in the wrong direction to my taste. Very convoluted and not simple clear actual == expected things. I recommend to start over and make it just follow the pattern that in the paramaterize we pass in something like [(input1, expected1)] and the test doesn't have any, or a tiny amount, of logic it just looks something like
def test_function(inputs, expected)
actual = function(inputs)
assert actual == expected
sbillinge
left a comment
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.
please see comments
|
@sbillinge Alright, ready for review! |
sbillinge
left a comment
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.
this is very close now. Just a few cleaning edits and we are done.
|
@sbillinge ready for review. |
sbillinge
left a comment
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.
please see comments
tests/test_packsmanager.py
Outdated
| examples_dir = example_cases / "case5" | ||
| pm = PacksManager(root_path=examples_dir) | ||
| target_dir = example_cases / "user_target" | ||
| actual = pm.copy_examples(examples_to_copy=input, target_dir=target_dir) |
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 see two possible issues here that are issues with the function signature.
- it looks as if
examples_to_copyis an optional parameter but maybe it should be required. If it remains optional we need to decide what the default behavior is. I guess, arguably, the default behavior could be to copy all the examples. So the decision is (a) make it required, not optional. or (b) leave it optional but have the default behavior to copy everything. - You seem to assigned what this function returns to be
actual, but this is not testing the behavior. The test should be that the files are actually copied correctly, not something that the function returns. In fact, arguably, the function should returnNone.
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.
For 1, It isn't an optional parameter. it should be require. I think the confusion comes from me being explicit about the variable name (ie examples_to_copy=input rather than input). I'll remove the param name here (and everywhere else that i may have left it).
For 2, I'll work on this right now. I'll get the path to the copied examples separately. Then, copy_examples will return None.
tests/test_packsmanager.py
Outdated
| actual = pm.copy_examples(examples_to_copy=input, target_dir=target_dir) | ||
| expected = [] | ||
| for path in expected_paths: | ||
| root_path = target_dir / path |
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.
root path is a bad name here. In what sense is this a root_path?
How about this for this work:
expected = [target_dir / path for path in expected_paths]
Then to test the files were copied correctly we would need something like
actual_gen = target_dir.rglob('*')
and syntax that iterates through the lists and (a) checks that they contain the same elements and (b) that the files exist and (c) optionally, but not necessarily, check that the files contain the right contents. I think (c) may be overkill, but strictly if we don't we could write the function that passes the test just by touching those files and not copying them. It will be some work though because I think we are creating those files empty so we would have to write something in them. I think there is a way to create and write them in one line though in conftest, so it could be quick to do. Let's just think about it.
tests/test_packsmanager.py
Outdated
| examples_dir = example_cases / "case5" | ||
| os.chdir(example_cases / "cwd") | ||
| pm = PacksManager(root_path=examples_dir) | ||
| paths = pm.copy_examples(examples_to_copy=["packA"], target_dir=input) |
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.
the comments above are relevant here.
tests/test_packsmanager.py
Outdated
| [ | ||
| ( # input not found (example or pack) | ||
| ["bad_example"], | ||
| ValueError, |
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.
normally we would check the error message. In this case we use the tests to define good (helpful) error messages.
tests/test_packsmanager.py
Outdated
| ValueError, | ||
| None, | ||
| ), | ||
| ( # path to dir already exists |
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.
please use the pattern # description of case. Expected behavior In general, this pattern is better above too, though the behavior is simple and captured well in the test, but here it deserves discussion. What do we want the function to do in this situation?
From a user perspective, I probably don't want a crash. For example, let's say I copy packA to begin with, then I love the code so much that I want to just copy all later, but I want the examples nice and tidily in the same location. When I type all it will find the already present packA examples. Rather than a crash here, I would probably want it to either skip over the already existing examples or overwrite them. To accomplish this, we could interrupt the program and ask user input, but much better is probably to have a default behavior that skips directories that exist and sends a warning, but also to have an option in the cli that is --force or --overwrite, that does the other behavior. The warning that gets printed could mention to rerun the program using --force if you want to overwrite existing examples. SOmething like that.
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.
Yes, I like the --force option, added it here.
tests/test_packsmanager.py
Outdated
| @pytest.mark.parametrize( | ||
| "bad_inputs,expected", | ||
| [ | ||
| (Path("nonexistent/path/target"), FileNotFoundError), # doesn't exist |
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.
please test error messages here too.
|
@sbillinge ready for review. I also left one response here #60 (comment). I used the following syntax to capture error messages, let me know if there is a better way to capture this Also, before you merge, let me know if it looks good and i can put this all on a clean PR |
sbillinge
left a comment
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.
please see comments
tests/test_packsmanager.py
Outdated
| expected = [target_dir / path for path in expected_paths] | ||
| assert actual == expected | ||
| for path in expected_paths: | ||
| dest = target_dir / path |
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.
this probably easier to read if we use the actual expected language rather than source and dest as we are not moving or copying anything. This looks like code that chatGPT would write, but please try and think like a reviewer if/when adopting such code.....
tests/test_packsmanager.py
Outdated
| # 4) Path to directory already exists. | ||
| # Expected: Raise a warning with the message. | ||
| ["ex1"], | ||
| "Target directory already exists. To overwrite use --force.", |
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.
put the behavior explicitly, something like ".... . Current versions of existing files have been left. To overwrite with new versions, please rerun specifying --force" Also, is it target directory or `"example directory: ex1" '
What behavior/message do we want if multiple examples are bad? We don't have test cases for that I think.
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 think print the list instead dirs will be okay, something like Target directory(ies) <list> already exist...
tests/test_packsmanager.py
Outdated
| Path("docs/examples/"), | ||
| ), | ||
| ( | ||
| # 5) No input provided. |
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.
this one is not needed. IT will be handled in the cli not here
tests/test_packsmanager.py
Outdated
| ( | ||
| # 1) Target doesn't exist. | ||
| # Expected: Raise an error that the target directory is missing. | ||
| Path("nonexistent/path/target"), |
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.
if the path doesn't exist, don't we want to create it?
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.
yes we can create it
tests/test_packsmanager.py
Outdated
| "Target directory does not exist", | ||
| ), | ||
| ( | ||
| # 2) Target is a file. |
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 don't think we need this one. We don't have to worry about this case. I guess the code will crash if we try and create a directory that is a file but we don't need a friendly error message that we test.
tests/test_packsmanager.py
Outdated
| "Target path is not a directory", | ||
| ), | ||
| ( | ||
| # 3) Target is nested in a file. |
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.
see above. TL:DR, I think we can remove this whole paramaterize
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.
okay, will remove
|
@sbillinge ready for review |
sbillinge
left a comment
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.
OK, 100% good on the tests now. Do you want to make a new PR with this version and then punch out the function?
|
@sbillinge yep let's do that! I can probably get to it later today. On my phone right now and not home |
|
closing bc opened a clean PR |
This test runs 70 tests. This breakdown is from the following 14 copy scenarios. Each copy scenario is written for each
caseXgenerated in the temp dir. we have 5 cases so14 * 5 = 70