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

Integration Tests For FeePerKb #2433

Merged
merged 6 commits into from
Jun 26, 2024

Conversation

wilmerrootstock
Copy link
Contributor

Description

Making use of the newly created InMemoryStorage class, create tests simulating different real-life scenarios, avoiding using mocks as much as possible.

Integration tests are written to observe the behavior simulating real-life scenarios and stressing the InMemoryStorage executing them one after another.

Motivation and Context

Get Coverage with more realistic scenarios, even more than the Unit Tests.

How Has This Been Tested?

Through Integration tests.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • Tests for the changes have been added (for bug fixes / features)
  • Requires Activation Code (Hard Fork)
  • Other information:

@wilmerrootstock wilmerrootstock requested a review from a team as a code owner June 1, 2024 22:39
Copy link

@apancorb apancorb left a comment

Choose a reason for hiding this comment

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

Looks very nice and readable, left two comments

assertFeePerKbValue(genesisFeePerKb);

/*
* 1st voting: authorizer 1 and 2 vote the same value
Copy link

Choose a reason for hiding this comment

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

I am wandering, can each of these sections be placed in its own test? Or is there a need for all of them to be chained in this manner?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey, Antonio!
Although we're working with UT's tools, this approach creates integration tests, that is, test the whole Fee Per KB module, for this reason, it is important to make different test cases stressing the InMemoryStorage executing one test after another, and observe the behavior interacting like a real-life scenario without isolate them.

Copy link
Contributor

@marcos-iov marcos-iov Jun 3, 2024

Choose a reason for hiding this comment

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

We should discuss this with the rest of the team @apancorb. The plan here was to create a test that simulates a real interaction with the fee per kb feature. That implies keeping the state and not reseting it between tests.

One option is to do it this way, in a single big test executing one action after the other. The other option is to do it in separate tests, sharing the same environment between tests. This last option implies that those tests will not be independent.

What do you think? Any other ideas?

Copy link

Choose a reason for hiding this comment

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

I see, for integration tests sharing state between tests is fine. I would recommend having each Xth voting section in its own small test and sharing state at the class level.

Check this article out that will describe how to set per-class lifecycle and how to set the ordering of tests if it matters. This might help you achieve what you want to create.

As a side note, integration tests are usually placed under the intTest directory next to main and test. Gradle natively supports this convention. Maybe in the future this is something we can adopt.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with @apancorb. This long test should be split using one of the options available for this case using junit.

Copy link
Contributor Author

@wilmerrootstock wilmerrootstock Jun 13, 2024

Choose a reason for hiding this comment

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

Refactoring Test Integration for Fee Per KB

  • Adding some annotations such as @testinstance, and @BeforeAll to help share state in the test.
  • Adding annotations such as @TestMethodOrder, and @order to create an order of test execution.
  • Adding Caller enum to get the code more expressive.
  • After adding the Caller enum, adapt the voteFeePerKb method to receive as an In Parameter RskAddress.
  • Removing voteFeePerKbByUnauthorizedCaller, getAuthorizedRskAddresses, and getUnauthorizedRskAddress methods since they are no longer needed after the adaptation of the Caller enum in the code.

P.S.: it's just missing to move this integration test to the integrationTest directory. I'm solving some dependency issues.

private RskAddress getUnauthorizedRskAddress() {
return new RskAddress("e2a5070b4e2cb77fe22dff05d9dcdc4d3eaa6ead");
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

What happens if, for example, the current fee per kb is 100_000L and the authorizers decide to vote for the same 100_000L? Does it get rejected? Does it throw an error?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey, Jere!
Brilliant contribution! In this case, 100_000L is set again as "the new fee per KB value".
I just added this case to the tests:
16th voting: authorized callers vote the same current fee per KB value

nathanieliov
nathanieliov previously approved these changes Jun 6, 2024
Copy link
Contributor

@nathanieliov nathanieliov left a comment

Choose a reason for hiding this comment

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

Very well done, Wilmer! Just a single comment, same as @apancorb: I would rather split the test into separate tests sharing the same context instance.

@marcos-iov marcos-iov force-pushed the fee-per-kb-refactor-integration branch from 7fc0436 to f1edb96 Compare June 6, 2024 15:49
@marcos-iov marcos-iov force-pushed the feature/integration-tests-fee-per-kb branch from 7f85689 to 4804699 Compare June 7, 2024 14:00
Base automatically changed from fee-per-kb-refactor-integration to master June 10, 2024 13:20
@Vovchyk Vovchyk dismissed nathanieliov’s stale review June 10, 2024 13:20

The base branch was changed.

@wilmerrootstock wilmerrootstock force-pushed the feature/integration-tests-fee-per-kb branch from 4804699 to 9a0297e Compare June 13, 2024 04:34
Comment on lines 36 to 51
Coin differentFeePerKbVote = Coin.valueOf(60_000L);
Coin maxFeePerKbVote = feePerKbConstants.getMaxFeePerKb();
Coin excessiveFeePerKbVote = maxFeePerKbVote.add(Coin.SATOSHI);
Coin genesisFeePerKb = feePerKbConstants.getGenesisFeePerKb();
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's best if we declare each of these near the place where they are about to be used

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

* Created to makes easier the way to get RskAddress of 3 authorized and 1 unauthorized Callers. It
* contains hex encoded string associated to each caller and return the RskAddress of each one.
*/
public enum Caller {
Copy link
Contributor

Choose a reason for hiding this comment

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

I wouldn't create this, at least not in a separate file. If it makes sense to have this enum then simply it put it inside the test class, it's the only place it's used

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But, we could use it in the UTs as well. We can think about having an isolated library project in the future for tests and create a .jar to be used as a kind of test library/framework, that could be used in cross-projects (RSKj/Powpeg-Node) and cross-tests (UTs and ITs). In the meantime, we might put all these objects together in a utils package. Creating it inside the class breaks the Single Responsibility Principle.

Copy link
Contributor

Choose a reason for hiding this comment

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

I like @wilmerrootstock idea very much about moving this out of the test for the benefit of reusability.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, in that case I'd move this to feeperkb package and rename it FeePerKbVoteCaller. What do you think?

I'm not a fan of generic util packages or classes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

@wilmerrootstock wilmerrootstock force-pushed the feature/integration-tests-fee-per-kb branch 2 times, most recently from 87b8496 to 058d47d Compare June 18, 2024 21:59
Comment on lines 23 to 24
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@TestInstance(Lifecycle.PER_CLASS)
Copy link

@apancorb apancorb Jun 20, 2024

Choose a reason for hiding this comment

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

Not sure, but I don't think the @TestInstance(Lifecycle.PER_CLASS) annotation is needed here since it is implied by @TestMethodOrder(MethodOrderer.OrderAnnotation.class)

Copy link
Contributor Author

@wilmerrootstock wilmerrootstock Jun 21, 2024

Choose a reason for hiding this comment

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

Hey, @apancorb!
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) doesn't have built-in @TestInstance(Lifecycle.PER_CLASS) in it. If we don't set @TestInstance(Lifecycle.PER_CLASS) it goes work Lifecycle.PER_METHOD by default. That means, if we are going to share a state of a variable in all methods, for instance, currentFeePerKb, it must be static. Apart from that, the method annotated with @BeforeAll must be static and all into it, static as well. That being said, I believe our best option is to use @TestInstance(Lifecycle.PER_CLASS).

Choose a reason for hiding this comment

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

Thanks!

* Created to makes easier the way to get RskAddress of 3 authorized and 1 unauthorized Callers. It
* contains hex encoded string associated to each caller and return the RskAddress of each one.
*/
public enum FeePerKbVoteCaller {

Choose a reason for hiding this comment

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

Are we expecting this to only be used by FeePerKbIntegrationTest? If that is the case, we can just declare them as constants in FeePerKbIntegrationTest

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey, @apancorb! Take a look at this thread, this topic was discussed in it:

#2433 (comment)

@marcos-iov marcos-iov force-pushed the feature/integration-tests-fee-per-kb branch from b982a47 to f4e06f2 Compare June 21, 2024 19:42
marcos-iov
marcos-iov previously approved these changes Jun 21, 2024
apancorb
apancorb previously approved these changes Jun 24, 2024
@wilmerrootstock wilmerrootstock dismissed stale reviews from apancorb and marcos-iov via 6da6299 June 24, 2024 15:05
@lucasvuotto
Copy link
Contributor

pipeline: run

@marcos-iov marcos-iov force-pushed the feature/integration-tests-fee-per-kb branch from 1831bde to b72f37a Compare June 25, 2024 15:51
@julia-zack julia-zack self-requested a review June 25, 2024 17:42
wilmerrootstock and others added 6 commits June 26, 2024 09:34
Making use of the newly created InMemoryStorage class, create tests simulating different real-life scenarios, avoiding using mocks as much as possible.

Integration tests are written to observe the behavior simulating real-life scenarios and stressing the InMemoryStorage executing them one after another.

White space before open brace

- Adding white space before open brace to enhance the indentation.

Improving Comments

Adding 16th voting test

- Authorized callers vote same current fee per KB value.

Refactoring Test Integration for Fee Per KB

- Adding some annotations such as @testinstance, and @BeforeAll to help sharing state in the test.
- Adding annotations such as @TestMethodOrder, and @order to create an order of test execution.
- Adding Caller enum to get the code more expressive.
- After adding the Caller enum, adapt the voteFeePerKb method to receive as an In Parameter RskAddress.
- Removing voteFeePerKbByUnauthorizedCaller, getAuthorizedRskAddresses, and getUnauthorizedRskAddress methods since they are no longer needed after the adaptation of the Caller enum in the code.

Renaming and Moving Enum to Another Package

- Renaming Enum from Caller to FeePerKbVoteCaller.
- Moving Enum from utils to feeperkb package.

Changing type of variable

- Changing type of variable from instance to local.

Renaming Test Methods

- Renaming Test Methods to fit our method names for IT.
- Removing JavaDocs for Methods since with new method names they are not needed anymore.

Renaming Class Name

- Renaming class name, to apply new naming conventions for Integration Tests(IT). This consists of adding at the end of the class name the suffix IT.

Changing differentFeePerKbVote From Variable To Constant.
- Fixing naming convention for a variable name to use camel case.

Improving Comment
Improving Method Name for @order(8)
Removing Unnecessary Comment

Removing Unnecessary Vote

- Removing unnecessary vote since it doesn't help to go straight to the point to the sense of the test method.
@marcos-iov marcos-iov force-pushed the feature/integration-tests-fee-per-kb branch from b72f37a to 6f62827 Compare June 26, 2024 12:36
Copy link

sonarcloud bot commented Jun 26, 2024

@marcos-iov
Copy link
Contributor

pipeline:run

@josedahlquist josedahlquist merged commit 2bbedf5 into master Jun 26, 2024
10 checks passed
@marcos-iov marcos-iov deleted the feature/integration-tests-fee-per-kb branch June 26, 2024 19:52
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.

8 participants