From ecb4562c29a7ac3bf3c82b5caf228b84480c0bf7 Mon Sep 17 00:00:00 2001 From: Jonathan Wren Date: Wed, 6 May 2020 18:13:36 -0700 Subject: [PATCH] Make sure testing cleans up after itself (#940) This adds the ability to run commands in a cache directory without the test writer knowing where the cache directory is located. This will let us expand later if we want to start using system temp folders, without having to rewrite any of our tests. * clean up extra directories after running behave * clean up white space issues * move repeated code into function * clean up behave code for creating cache directories * Fix for windows shell parsing in our test suite Co-authored-by: Micah Jerome Ellison --- features/environment.py | 17 ++++++++------- features/exporting.feature | 14 ++++++++---- features/regression.feature | 39 ++++++++++++++++++++-------------- features/steps/core.py | 11 ++++++---- features/steps/export_steps.py | 30 ++++++++++++++++---------- 5 files changed, 68 insertions(+), 43 deletions(-) diff --git a/features/environment.py b/features/environment.py index 02f2747e..a75bba4d 100644 --- a/features/environment.py +++ b/features/environment.py @@ -3,6 +3,13 @@ import os import sys +def clean_all_working_dirs(): + for folder in ("configs", "journals", "cache"): + working_dir = os.path.join("features", folder) + if os.path.exists(working_dir): + shutil.rmtree(working_dir) + + def before_feature(context, feature): # add "skip" tag # https://stackoverflow.com/a/42721605/4276230 @@ -18,10 +25,7 @@ def before_feature(context, feature): def before_scenario(context, scenario): """Before each scenario, backup all config and journal test data.""" # Clean up in case something went wrong - for folder in ("configs", "journals"): - working_dir = os.path.join("features", folder) - if os.path.exists(working_dir): - shutil.rmtree(working_dir) + clean_all_working_dirs() for folder in ("configs", "journals"): original = os.path.join("features", "data", folder) @@ -48,7 +52,4 @@ def before_scenario(context, scenario): def after_scenario(context, scenario): """After each scenario, restore all test data and remove working_dirs.""" - for folder in ("configs", "journals"): - working_dir = os.path.join("features", folder) - if os.path.exists(working_dir): - shutil.rmtree(working_dir) + clean_all_working_dirs() diff --git a/features/exporting.feature b/features/exporting.feature index 89abfd0e..7f4df59f 100644 --- a/features/exporting.feature +++ b/features/exporting.feature @@ -122,10 +122,16 @@ Feature: Exporting a Journal Scenario: Export to yaml Given we use the config "tags.yaml" - And we created a directory named "exported_journal" - When we run "jrnl --export yaml -o exported_journal" - Then "exported_journal" should contain the files ["2013-04-09_i-have-an-idea.md", "2013-06-10_i-met-with-dan.md"] - And the content of exported yaml "exported_journal/2013-04-09_i-have-an-idea.md" should be + And we create cache directory "exported_journal" + When we run "jrnl --export yaml -o {cache_dir}" with cache directory "exported_journal" + Then cache directory "exported_journal" should contain the files + """ + [ + "2013-04-09_i-have-an-idea.md", + "2013-06-10_i-met-with-dan.md" + ] + """ + And the content of file "2013-04-09_i-have-an-idea.md" in cache directory "exported_journal" should be """ title: I have an @idea: date: 2013-04-09 15:39 diff --git a/features/regression.feature b/features/regression.feature index 033ec95c..5342b746 100644 --- a/features/regression.feature +++ b/features/regression.feature @@ -76,30 +76,30 @@ Feature: Zapped bugs should stay dead. Then the output should not contain "But I'm better." Scenario: Create entry using day of the week as entry date. - Given we use the config "basic.yaml" - When we run "jrnl monday: This is an entry on a Monday." - Then we should see the message "Entry added" - When we run "jrnl -1" + Given we use the config "basic.yaml" + When we run "jrnl monday: This is an entry on a Monday." + Then we should see the message "Entry added" + When we run "jrnl -1" Then the output should contain "monday at 9am" in the local time Then the output should contain "This is an entry on a Monday." Scenario: Create entry using day of the week abbreviations as entry date. - Given we use the config "basic.yaml" - When we run "jrnl fri: This is an entry on a Friday." - Then we should see the message "Entry added" - When we run "jrnl -1" - Then the output should contain "friday at 9am" in the local time + Given we use the config "basic.yaml" + When we run "jrnl fri: This is an entry on a Friday." + Then we should see the message "Entry added" + When we run "jrnl -1" + Then the output should contain "friday at 9am" in the local time Scenario: Displaying entries using -on today should display entries created today. Given we use the config "basic.yaml" - When we run "jrnl today: Adding an entry right now." + When we run "jrnl today: Adding an entry right now." Then we should see the message "Entry added" When we run "jrnl -on today" Then the output should contain "Adding an entry right now." Scenario: Displaying entries using -from day should display correct entries Given we use the config "basic.yaml" - When we run "jrnl yesterday: This thing happened yesterday" + When we run "jrnl yesterday: This thing happened yesterday" Then we should see the message "Entry added" When we run "jrnl today at 11:59pm: Adding an entry right now." Then we should see the message "Entry added" @@ -112,7 +112,7 @@ Feature: Zapped bugs should stay dead. Scenario: Displaying entries using -from and -to day should display correct entries Given we use the config "basic.yaml" - When we run "jrnl yesterday: This thing happened yesterday" + When we run "jrnl yesterday: This thing happened yesterday" Then we should see the message "Entry added" When we run "jrnl today at 11:59pm: Adding an entry right now." Then we should see the message "Entry added" @@ -148,10 +148,17 @@ Feature: Zapped bugs should stay dead. # See issues #768 and #881 Scenario: Add a blank line to YAML export is there isn't one already Given we use the config "deletion.yaml" - And we created a directory named "bug768" - When we run "jrnl --export yaml -o bug768" - Then "bug768" should contain the files ["2019-10-29_first-entry.md", "2019-10-29_second-entry.md", "2019-10-29_third-entry.md"] - And the content of exported yaml "bug768/2019-10-29_third-entry.md" should be + And we create cache directory "bug768" + When we run "jrnl --export yaml -o {cache_dir}" with cache directory "bug768" + Then cache directory "bug768" should contain the files + """ + [ + "2019-10-29_first-entry.md", + "2019-10-29_second-entry.md", + "2019-10-29_third-entry.md" + ] + """ + And the content of file "2019-10-29_third-entry.md" in cache directory "bug768" should be """ title: Third entry. date: 2019-10-29 11:13 diff --git a/features/steps/core.py b/features/steps/core.py index 8465c4a9..30e0e101 100644 --- a/features/steps/core.py +++ b/features/steps/core.py @@ -45,9 +45,7 @@ keyring.set_keyring(TestKeyring()) def ushlex(command): - if sys.version_info[0] == 3: - return shlex.split(command) - return map(lambda s: s.decode("UTF8"), shlex.split(command.encode("utf8"))) + return shlex.split(command, posix="win32" not in sys.platform) def read_journal(journal_name="default"): @@ -151,7 +149,12 @@ def run_with_input(context, command, inputs=""): @when('we run "{command}"') -def run(context, command): +@when('we run "{command}" with cache directory "{cache_dir}"') +def run(context, command, cache_dir=None): + if cache_dir is not None: + cache_dir = os.path.join("features", "cache", cache_dir) + command = command.format(cache_dir=cache_dir) + args = ushlex(command)[1:] try: cli.run(args or None) diff --git a/features/steps/export_steps.py b/features/steps/export_steps.py index 40127ecc..c75cf331 100644 --- a/features/steps/export_steps.py +++ b/features/steps/export_steps.py @@ -85,17 +85,24 @@ def assert_xml_output_tags(context, expected_tags_json_list): assert actual_tags == set(expected_tags), [actual_tags, set(expected_tags)] -@given('we created a directory named "{dir_name}"') +@given('we create cache directory "{dir_name}"') def create_directory(context, dir_name): - if os.path.exists(dir_name): - shutil.rmtree(dir_name) - os.mkdir(dir_name) + working_dir = os.path.join("features", "cache", dir_name) + if os.path.exists(working_dir): + shutil.rmtree(working_dir) + os.makedirs(working_dir) -@then('"{dir_name}" should contain the files {expected_files_json_list}') -def assert_dir_contains_files(context, dir_name, expected_files_json_list): - actual_files = os.listdir(dir_name) - expected_files = json.loads(expected_files_json_list) +@then('cache directory "{dir_name}" should contain the files') +@then( + 'cache directory "{dir_name}" should contain the files {expected_files_json_list}' +) +def assert_dir_contains_files(context, dir_name, expected_files_json_list="[]"): + working_dir = os.path.join("features", "cache", dir_name) + actual_files = os.listdir(working_dir) + + expected_files = context.text or expected_files_json_list + expected_files = json.loads(expected_files) # sort to deal with inconsistent default file ordering on different OS's actual_files.sort() @@ -104,11 +111,12 @@ def assert_dir_contains_files(context, dir_name, expected_files_json_list): assert actual_files == expected_files, [actual_files, expected_files] -@then('the content of exported yaml "{file_path}" should be') -def assert_exported_yaml_file_content(context, file_path): +@then('the content of file "{file_path}" in cache directory "{cache_dir}" should be') +def assert_exported_yaml_file_content(context, file_path, cache_dir): expected_content = context.text.strip().splitlines() + full_file_path = os.path.join("features", "cache", cache_dir, file_path) - with open(file_path, "r") as f: + with open(full_file_path, "r") as f: actual_content = f.read().strip().splitlines() for actual_line, expected_line in zip(actual_content, expected_content):