-
Notifications
You must be signed in to change notification settings - Fork 266
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
Conversation
There was a problem hiding this 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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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 thevoteFeePerKb
method to receive as an In ParameterRskAddress
. - Removing
voteFeePerKbByUnauthorizedCaller
,getAuthorizedRskAddresses
, andgetUnauthorizedRskAddress
methods since they are no longer needed after the adaptation of theCaller
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.
rskj-core/src/test/java/co/rsk/peg/feeperkb/FeePerKbIntegrationTest.java
Outdated
Show resolved
Hide resolved
private RskAddress getUnauthorizedRskAddress() { | ||
return new RskAddress("e2a5070b4e2cb77fe22dff05d9dcdc4d3eaa6ead"); | ||
} | ||
} |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this 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.
7fc0436
to
f1edb96
Compare
7f85689
to
4804699
Compare
4804699
to
9a0297e
Compare
Coin differentFeePerKbVote = Coin.valueOf(60_000L); | ||
Coin maxFeePerKbVote = feePerKbConstants.getMaxFeePerKb(); | ||
Coin excessiveFeePerKbVote = maxFeePerKbVote.add(Coin.SATOSHI); | ||
Coin genesisFeePerKb = feePerKbConstants.getGenesisFeePerKb(); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
87b8496
to
058d47d
Compare
rskj-core/src/test/java/co/rsk/peg/feeperkb/FeePerKbIntegrationTest.java
Outdated
Show resolved
Hide resolved
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) | ||
@TestInstance(Lifecycle.PER_CLASS) |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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)
.
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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:
rskj-core/src/test/java/co/rsk/peg/feeperkb/FeePerKbIntegrationTest.java
Outdated
Show resolved
Hide resolved
b982a47
to
f4e06f2
Compare
rskj-core/src/test/java/co/rsk/peg/feeperkb/FeePerKbVoteCaller.java
Outdated
Show resolved
Hide resolved
6da6299
pipeline: run |
1831bde
to
b72f37a
Compare
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.
b72f37a
to
6f62827
Compare
|
pipeline:run |
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
Checklist: