-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[feat] Add generate-rtd command (#82)
- Loading branch information
Showing
10 changed files
with
470 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
"""Command for generating the reference tests directory from solutions branches | ||
in template repositories. | ||
""" | ||
import shutil | ||
import pathlib | ||
import tempfile | ||
from typing import List, Iterable, Mapping | ||
|
||
import git | ||
|
||
import repobee_plug as plug | ||
|
||
JUNIT4_COMMAND_CATEGORY = plug.cli.category( | ||
name="junit4", | ||
action_names=["generate-rtd"], | ||
help="help commands for the junit4 plugin", | ||
) | ||
|
||
_COMMAND_DESCRIPTION = """ | ||
Generate the reference tests directory (RTD) from template repositories by | ||
extracting any Java test classes from the template. For each assignment | ||
specified, a subdirectory in the reference tests directory (RTD) is created | ||
with the name of the assignment. When generating the test directory for a given | ||
assignment X, there must not be an X directory already in the RTD. If you want | ||
to refresh the tests for an assignment X, then delete its corresponding | ||
subdirectory before running this command. WARNING: This command is in alpha and | ||
behavior may change in coming updates. | ||
""".replace( | ||
"\n", " " | ||
).strip() | ||
|
||
|
||
class GenerateRTD(plug.Plugin, plug.cli.Command): | ||
__settings__ = plug.cli.command_settings( | ||
action=JUNIT4_COMMAND_CATEGORY.generate_rtd, | ||
help="generate the reference tests directory by extracting test " | ||
"classes from template repositories (note: alpha test)", | ||
description=_COMMAND_DESCRIPTION, | ||
base_parsers=[ | ||
plug.cli.BaseParser.ASSIGNMENTS, | ||
plug.cli.BaseParser.TEMPLATE_ORG, | ||
], | ||
) | ||
|
||
reference_tests_dir = plug.cli.option( | ||
help="path to place the root reference tets directory at", | ||
converter=pathlib.Path, | ||
required=True, | ||
) | ||
branch = plug.cli.option( | ||
help="the branch to search for reference tests in each template " | ||
"repository", | ||
required=True, | ||
) | ||
|
||
def command(self, api: plug.PlatformAPI): | ||
existing_test_dirs = _get_existing_assignment_test_dirs( | ||
self.reference_tests_dir, self.args.assignments | ||
) | ||
if existing_test_dirs: | ||
return plug.Result( | ||
name=str(JUNIT4_COMMAND_CATEGORY.generate_rtd), | ||
msg=_format_failure_message(existing_test_dirs), | ||
status=plug.Status.ERROR, | ||
) | ||
|
||
assignment_names_progress = plug.cli.io.progress_bar( | ||
self.args.assignments, | ||
desc="Processing template repos", | ||
unit="repo", | ||
) | ||
assignment_test_classes = {} | ||
for assignment_name in assignment_names_progress: | ||
extracted_test_classes = _generate_assignment_tests_dir( | ||
assignment_name, | ||
self.branch, | ||
self.args.template_org_name, | ||
self.reference_tests_dir, | ||
api, | ||
) | ||
assignment_test_classes[assignment_name] = extracted_test_classes | ||
|
||
return plug.Result( | ||
name=str(JUNIT4_COMMAND_CATEGORY.generate_rtd), | ||
msg=_format_success_message(assignment_test_classes), | ||
status=plug.Status.SUCCESS, | ||
) | ||
|
||
|
||
def _generate_assignment_tests_dir( | ||
assignment_name: str, | ||
branch: str, | ||
template_org_name: str, | ||
rtd: pathlib.Path, | ||
api: plug.PlatformAPI, | ||
) -> List[pathlib.Path]: | ||
"""Generate the reference tests directory for a single assignment as a | ||
subdirectory of the reference tests dir with the same name as the | ||
assignment. The assignment test directory must not already exist. | ||
""" | ||
assignment_test_dir = rtd / assignment_name | ||
assignment_test_dir.mkdir(parents=True, exist_ok=False) | ||
|
||
with tempfile.TemporaryDirectory() as tmpdir: | ||
workdir = pathlib.Path(tmpdir) | ||
repo_url = _get_authed_url(assignment_name, template_org_name, api) | ||
template_repo = _clone_repo_to( | ||
repo_url, branch, workdir / assignment_name | ||
) | ||
return list( | ||
_copy_test_classes( | ||
src_dir=pathlib.Path(template_repo.working_tree_dir), | ||
dst_dir=assignment_test_dir, | ||
) | ||
) | ||
|
||
|
||
def _copy_test_classes( | ||
src_dir: pathlib.Path, dst_dir: pathlib.Path | ||
) -> Iterable[pathlib.Path]: | ||
reference_test_classes = src_dir.rglob("*Test.java") | ||
for test_class in reference_test_classes: | ||
shutil.copy( | ||
src=test_class, dst=dst_dir / test_class.name, | ||
) | ||
yield test_class.relative_to(src_dir) | ||
|
||
|
||
def _clone_repo_to( | ||
repo_url: str, branch: str, to_path: pathlib.Path, | ||
) -> git.Repo: | ||
template_repo = git.Repo.clone_from(repo_url, to_path) | ||
template_repo.git.checkout(branch) | ||
return template_repo | ||
|
||
|
||
def _get_authed_url( | ||
assignment_name: str, org_name: str, api: plug.PlatformAPI | ||
) -> str: | ||
# FIXME temporary workaround as insert_auth is not implemented | ||
# in FakeAPI.get_repo_urls. Should be fixed in RepoBee 3.4. | ||
return api.insert_auth( | ||
api.get_repo_urls([assignment_name], org_name=org_name,)[0] | ||
) | ||
|
||
|
||
def _get_existing_assignment_test_dirs( | ||
rtd: pathlib.Path, assignment_names: List[str] | ||
) -> List[pathlib.Path]: | ||
return [ | ||
rtd / assignment_name | ||
for assignment_name in assignment_names | ||
if (rtd / assignment_name).exists() | ||
] | ||
|
||
|
||
def _format_success_message( | ||
assignment_test_classes: Mapping[str, Iterable[pathlib.Path]] | ||
) -> str: | ||
return "\n".join( | ||
f"{assignment_name}: {', '.join(tc.name for tc in test_classes)}" | ||
for assignment_name, test_classes in assignment_test_classes.items() | ||
) | ||
|
||
|
||
def _format_failure_message(existing_test_dirs: Iterable[pathlib.Path]) -> str: | ||
return ( | ||
f"Some assignment test directories already exist, please delete " | ||
f"and try again: {', '.join(map(str, existing_test_dirs))}" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
colored | ||
daiquiri | ||
repobee>=3.0.0-alpha.7 | ||
repobee>=3.3.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
.../fakeapi_integration_tests/template_repos/junit4-task-1/master_branch/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
This repo should pass all tests |
20 changes: 20 additions & 0 deletions
20
tests/fakeapi_integration_tests/template_repos/junit4-task-1/master_branch/src/Fibo.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/** | ||
* Class for calculating Fibonacci numbers. | ||
*/ | ||
|
||
public class Fibo { | ||
private long prev; | ||
private long current; | ||
|
||
public Fibo() { | ||
// TODO constructor | ||
} | ||
|
||
/** | ||
* Generate the next Fibonacci number. | ||
*/ | ||
public long next() { | ||
// TODO implement method | ||
return 0; | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
...keapi_integration_tests/template_repos/junit4-task-1/solutions_branch/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
This repo should pass all tests |
23 changes: 23 additions & 0 deletions
23
tests/fakeapi_integration_tests/template_repos/junit4-task-1/solutions_branch/src/Fibo.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/** | ||
* Class for calculating Fibonacci numbers. | ||
*/ | ||
|
||
public class Fibo { | ||
private long prev; | ||
private long current; | ||
|
||
public Fibo() { | ||
prev = 0; | ||
current = 1; | ||
} | ||
|
||
/** | ||
* Generate the next Fibonacci number. | ||
*/ | ||
public long next() { | ||
long ret = prev; | ||
prev = current; | ||
current = ret + current; | ||
return ret; | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
...fakeapi_integration_tests/template_repos/junit4-task-1/solutions_branch/src/FiboTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import org.junit.Test; | ||
import org.junit.Before; | ||
import static org.junit.Assert.*; | ||
|
||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.hamcrest.CoreMatchers.*; | ||
|
||
public class FiboTest { | ||
@Test | ||
public void correctlyGeneratesFirst10Numbers() { | ||
Fibo f = new Fibo(); | ||
long[] expected = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34}; | ||
long[] actual = new long[10]; | ||
|
||
for (int i = 0; i < 10; i++) { | ||
actual[i] = f.next(); | ||
} | ||
|
||
assertThat(actual, equalTo(expected)); | ||
} | ||
|
||
@Test | ||
public void correctlyGeneratesFiftiethNumber() { | ||
// note that the first number is counted as the 0th | ||
Fibo f = new Fibo(); | ||
|
||
for (int i = 0; i < 50; i++) { | ||
f.next(); | ||
} | ||
|
||
assertThat(f.next(), equalTo(12586269025l)); | ||
} | ||
} |
Oops, something went wrong.