Skip to content
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

review: test: add test for insertAllFields method #3995

Merged
merged 6 commits into from
Jun 18, 2021
Merged

review: test: add test for insertAllFields method #3995

merged 6 commits into from
Jun 18, 2021

Conversation

Rohitesh-Kumar-Jain
Copy link
Contributor

#1818

Hi, I have added a new test for insertAllFilelds method of the Substituion class, this test improves code coverage, mutation converge and test strength all from 0% to 100%.

Here's the report before improvement.

Screenshot 2021-06-16 at 6 22 03 PM

I have manually tested that this test is killing that mutation.

Under the hood, it is testing more code,

Screenshot 2021-06-16 at 6 28 03 PM

so I will run Descartes again when the iterations for this PR will end and this gets merged. Until then I believe I should work on some other poorly tested classes suggested by @slarse?

Link to #3967

Copy link
Collaborator

@slarse slarse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Rohitesh-Kumar-Jain,

It's great that your testing the Substitution class, it looks woefully undertested.

The PR needs some work, however. I've added quite a lot of comments in the code itself. In addition, I think this also calls for creating a new test class, SubstitutionTest, because we will need to add more tests for that class in particular.

Ping me when you're done :)

Comment on lines 1 to 21
package spoon.test.template.testclasses;

import spoon.template.Local;
import spoon.template.Parameter;
import spoon.template.StatementTemplate;

public class InsertAllFieldsTemplate extends StatementTemplate {
@Parameter
String _parameter_;
String testString = "goodName";

@Local
public InsertAllFieldsTemplate(String parameter) {
_parameter_ = parameter;
}

@Override
public void statement() {
System.out.println(_parameter_);
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define this template right after the test instead, as a nested type in the test file. This is a crucial part of the test so we want to keep it close.

Also, consider its name. Does this template really insert all fields? I think a name such as SingleFieldTemplate is more descriptive.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally, the template does not align with the test. From what I can surmise of the contract and test, what you're testing is that the single field testString is inserted. To test just that, you should create a minimal template for testing just that.

public class InsertAllFieldsTemplate extends StatementTemplate {
    String testString = "goodName";

    @Override
    public void statement() { }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch 😅

src/test/java/spoon/test/template/TemplateTest.java Outdated Show resolved Hide resolved
src/test/java/spoon/test/template/TemplateTest.java Outdated Show resolved Hide resolved
@@ -900,6 +901,28 @@ public void testSubstituteInnerClass() {
assertEquals("x.Result$Inner",fr.getDeclaringType().getQualifiedName());
}

@Test
public void testSubstitutionInsertAllFields() {
// contract: insertAllFields method of the Substitution class inserts all the fields from a given template by substituting all the template parameters by their values.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This contract does not adequately describe the test. What actually happens in this test is that a single field, String testString = "goodName"; is inserted into the created class. There is no substitution going on, there is only a single as-is field insertion.

A more apt description would be something like "Substitution.insertAllFields inserts the only field from a single-field template into the target class"

Additionally, the test actually only verifies that the field has the correct name, so it doesn't verify the field as a whole.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I have changed the contract, I thoughtt I was supposed to write what the method is doing in the contract, than what is test is supposed to do.

test actually only verifies that the field has the correct name, so it doesn't verify the field as a whole.

Yes, I have added another assertion for checking the assignment of the field.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The contract should state any relevant preconditions for the test, method/class/etc is being tested, and what the expected out come is. How one gets from the preconditions to the expected outcome is an implementation detail a test in general is not concerned with :)

Sometimes it may be necessary to test an implementation detail, especially when testing corner cases or reproducing bugs. Then it may be relevant to explain such things in the contract. So, as with everything, this is not a rule set in stone, but rather a general guideline.

Assume that pretty much all of my feedback is either a general guideline, or just my opinion, or both.

@Rohitesh-Kumar-Jain
Copy link
Contributor Author

I think this also calls for creating a new test class, SubstitutionTest

Yes, I have created a new test class for SubstitutionTest, and the PR is once again ready to review @slarse.

Copy link
Collaborator

@slarse slarse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Rohitesh-Kumar-Jain,

So, this is good, but I think it can be even better. I also think that my initial review was a bit unclear and blabbery, and had it been better this would have been ready to merge now. See the review comments for more details.

An additional note: I think this is a test that could benefit from arrange, act and assert comments, because it's not entirely clear at first glance which phase is where, especially when it comes to arrange and act, as the arrangement is so large.

src/test/java/spoon/test/template/SubstitutionTest.java Outdated Show resolved Hide resolved
List<String> actualFieldNames = targetType.getFields().stream()
.map(CtField::getSimpleName)
.collect(Collectors.toList());
// verifies that the field has correct name
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the kind of comment that I would recommend you to avoid: it just says what the code does. The assertion is entirely clear on its own and should not have a comment explaining what it asserts.

Comment on lines 22 to 27
public class SingleFieldTemplate extends StatementTemplate {
String testString = "goodName";

@Override
public void statement() { }
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a personal preference of mine, and others may think otherwise, but I would put this below the test. I like to read files top-down, so if a method A uses a method or class B which is defined in the same file, then A is defined before B.

Again, I think this is a matter of taste, and you should form your own opinion. If you agree, then move the class down. If you disagree, feel free to keep it where it is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will place it downwards with no issues, actually, the first programming language that I learnt was C++, and in that one should declare the function at the top of the file calling the function, so probably I have this habit from there.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally understand, and as I said it's a matter of taste. Some prefer declaring functions before they are used, while others like me prefer to declare them just after they are used. There's no right or wrong, but in Java I find that the latter is more common.

@Rohitesh-Kumar-Jain
Copy link
Contributor Author

@slarse feel free to suggest changes for 3rd iteration if the PR needs improvement. I understand the purpose of GSoC is not to churn a lot of code, but to merge quality code in production and for students to learn new things and change their old habits : )

Copy link
Collaborator

@slarse slarse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@slarse feel free to suggest changes for 3rd iteration if the PR needs improvement. I understand the purpose of GSoC is not to churn a lot of code, but to merge quality code in production and for students to learn new things and change their old habits : )

This test is now of much higher quality than most other tests in Spoon (including tests I've written myself). I can't speak for the purpose of GSoC as I'm not officially involved, but the code quality here is very good. You're learning, and my reviews will grow shorter and shorter as you do.

@slarse slarse merged commit 9d43ea3 into INRIA:master Jun 18, 2021
@Rohitesh-Kumar-Jain Rohitesh-Kumar-Jain deleted the add-test-for-insertallfields branch June 18, 2021 06:23
@monperrus monperrus mentioned this pull request Aug 19, 2021
woutersmeenk pushed a commit to woutersmeenk/spoon that referenced this pull request Aug 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants