Skip to content

Commit 173f87d

Browse files
committed
generate correct function names in tests
Previously, the test function contained a hardcoded TODO which had to be adjusted by the exercise author. Now, the template references a variable fn_names, which was previously read from lib.rs. Meaning that, once the lib.rs stub is completed, the tests will be generated with the correct function names.
1 parent 8cacd6b commit 173f87d

3 files changed

Lines changed: 41 additions & 16 deletions

File tree

rust-tooling/src/bin/generate_exercise.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,13 @@ fn make_configlet_generate_what_it_can(slug: &str) {
176176
}
177177

178178
fn generate_exercise_files(slug: &str, is_update: bool) {
179-
let exercise = exercise_generation::new(slug);
179+
let fn_names = if is_update {
180+
read_fn_names_from_lib_rs(slug)
181+
} else {
182+
vec!["TODO".to_string()]
183+
};
184+
185+
let exercise = exercise_generation::new(slug, fn_names);
180186

181187
let exercise_path = PathBuf::from("exercises/practice").join(slug);
182188

@@ -201,3 +207,14 @@ fn generate_exercise_files(slug: &str, is_update: bool) {
201207
)
202208
.unwrap();
203209
}
210+
211+
fn read_fn_names_from_lib_rs(slug: &str) -> Vec<String> {
212+
let lib_rs =
213+
std::fs::read_to_string(format!("exercises/practice/{}/src/lib.rs", slug)).unwrap();
214+
215+
lib_rs
216+
.split("fn ")
217+
.skip(1)
218+
.map(|f| f.split_once('(').unwrap().0.to_string())
219+
.collect()
220+
}

rust-tooling/src/default_test_template.tera

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
{% if loop.index != 1 -%}
44
#[ignore]
55
{% endif -%}
6-
fn {{ test.description | replace(from=" ", to="_") }}() {
6+
fn {{ test.description | lower | replace(from=" ", to="_") }}() {
77
let input = {{ test.input }};
8-
let output = {{ crate_name }}::TODO(input);
8+
let output = {{ crate_name }}::{{ fn_names[0] }}(input);
99
let expected = {{ test.expected }};
1010
assert_eq!(output, expected);
1111
}

rust-tooling/src/exercise_generation.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,17 @@ pub struct GeneratedExercise {
1414
pub tests: String,
1515
}
1616

17-
pub fn new(slug: &str) -> GeneratedExercise {
17+
pub fn new(slug: &str, fn_names: Vec<String>) -> GeneratedExercise {
1818
let crate_name = slug.replace('-', "_");
19+
let first_fn_name = &fn_names[0];
1920

2021
GeneratedExercise {
2122
gitignore: GITIGNORE.into(),
2223
manifest: generate_manifest(&crate_name),
23-
lib_rs: generate_lib_rs(&crate_name),
24-
example: EXAMPLE_RS.into(),
24+
lib_rs: generate_lib_rs(&crate_name, first_fn_name),
25+
example: generate_example_rs(first_fn_name),
2526
test_template: TEST_TEMPLATE.into(),
26-
tests: generate_tests(slug),
27+
tests: generate_tests(slug, fn_names),
2728
}
2829
}
2930

@@ -46,22 +47,28 @@ fn generate_manifest(crate_name: &str) -> String {
4647
)
4748
}
4849

49-
fn generate_lib_rs(crate_name: &str) -> String {
50+
fn generate_lib_rs(crate_name: &str, fn_name: &str) -> String {
5051
format!(
5152
concat!(
52-
"pub fn TODO(input: TODO) -> TODO {{\n",
53+
"pub fn {fn_name}(input: TODO) -> TODO {{\n",
5354
" todo!(\"use {{input}} to implement {crate_name}\")\n",
5455
"}}\n",
5556
),
56-
crate_name = crate_name
57+
fn_name = fn_name,
58+
crate_name = crate_name,
5759
)
5860
}
5961

60-
static EXAMPLE_RS: &str = "\
61-
pub fn TODO(input: TODO) -> TODO {
62-
TODO
62+
fn generate_example_rs(fn_name: &str) -> String {
63+
format!(
64+
concat!(
65+
"pub fn {fn_name}(input: TODO) -> TODO {{\n",
66+
" TODO\n",
67+
"}}\n",
68+
),
69+
fn_name = fn_name
70+
)
6371
}
64-
";
6572

6673
static TEST_TEMPLATE: &str = include_str!("default_test_template.tera");
6774

@@ -74,7 +81,7 @@ fn extend_single_cases(single_cases: &mut Vec<SingleTestCase>, cases: Vec<TestCa
7481
}
7582
}
7683

77-
fn generate_tests(slug: &str) -> String {
84+
fn generate_tests(slug: &str, fn_names: Vec<String>) -> String {
7885
let cases = get_canonical_data(slug).cases;
7986
let excluded_tests = get_excluded_tests(slug);
8087
let mut template = get_test_emplate(slug).unwrap();
@@ -90,7 +97,8 @@ fn generate_tests(slug: &str) -> String {
9097

9198
let mut context = Context::new();
9299
context.insert("crate_name", &slug.replace('-', "_"));
100+
context.insert("fn_names", &fn_names);
93101
context.insert("cases", &single_cases);
94102

95-
template.render("test_template.tera", &context).unwrap()
103+
template.render("test_template.tera", &context).unwrap().trim_start().into()
96104
}

0 commit comments

Comments
 (0)