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

feat: Add HTTP Server TCK #8499

Merged
merged 13 commits into from Dec 20, 2022
Merged

feat: Add HTTP Server TCK #8499

merged 13 commits into from Dec 20, 2022

Conversation

sdelamo
Copy link
Collaborator

@sdelamo sdelamo commented Dec 19, 2022

Adds a new module http-server-tck

This module contains multiple tests for a Micronaut HTTP Server. Those tests were ported from the AWS Module.

It has an API ServerUnderTest and ServerUnderTestProvider which allows registering a module, implementing the TCK easily via a service loader.

It contains a test module test-suite-http-server-tck-netty which runs the TCK against micronaut-http-server-netty.

Adds a new module `http-server-tck`

This module contains multiple tests for a Micronaut HTTP Server.  Those tests were ported from the AWS Module.

It has an API `ServerUnderTest` and `ServerUnderTestProvider` which allows registering a module, implementing the TCK easily via a service loader.

It contains a test module `test-suite-http-server-tck-netty` which runs the TCK against `micronaut-http-server-netty`.
Copy link
Member

@yawkat yawkat left a comment

Choose a reason for hiding this comment

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

the whole test harness seems a bit convoluted. couldnt these be normal junit tests that access the server implementation using a rule or something?

sdelamo added a commit to micronaut-projects/micronaut-aws that referenced this pull request Dec 19, 2022
@sdelamo
Copy link
Collaborator Author

sdelamo commented Dec 19, 2022

the whole test harness seems a bit convoluted. couldnt these be normal junit tests that access the server implementation using a rule or something?

Not sure what you are proposing. Please, create a PR with this one as the base with your proposal

See linked PRs, specially in azure and lambda to see ServerUnderTest implementations for non EmbeddedServer solutions.

@yawkat
Copy link
Member

yawkat commented Dec 19, 2022

i dont mean the ServerUnderTest necessarily, i just want the tests to not be default methods in interfaces. e.g. by configuring junit to run the tests from the main tck module in the netty module.

@melix what do you think, is there a better way to achieve this?

@dstepanov
Copy link
Contributor

Why can't we have ordinary Spock tests as we have before? It should have been enough to copy existing Netty tests, and different implementations would provide a server implementation.

@dstepanov
Copy link
Contributor

I feel like you created some testing framework when it's not needed at all.

@melix
Copy link
Contributor

melix commented Dec 19, 2022

It should be possible to have tests exposed as a transitive dependency. By default Gradle will only add the tests from src/test on test classpath, but we can setup things differently, so that a test suite is added. The thing is how you get the thing under test injected into those tests. We can probably have several options here (like a static setter, or a Java service loader).

@yawkat
Copy link
Member

yawkat commented Dec 19, 2022

@melix getting the right server implementation injected is already solved using ServiceLoader in this PR. i think that approach is fine.

@melix
Copy link
Contributor

melix commented Dec 19, 2022

Right so it should only be a matter of:

  • having a test suite exposed as a consumable dependency
  • having that test suite injected as a dependency on the test classpath of the projects under test

I think we already do something like this in micronaut-data.

@dstepanov
Copy link
Contributor

There are a few ways:

@yawkat
Copy link
Member

yawkat commented Dec 19, 2022

extending each test is not workable here, since we will have tck implementations in different repositories. it's too easy to miss a test.

@sdelamo
Copy link
Collaborator Author

sdelamo commented Dec 19, 2022

The requisite is that we need to publish a library with tests. And use that library in different repositories (servlet, azure, azure).

I think it is safer to publish a standard java library with interfaces and consume it s proposed in this PR than complicating the build.

To run the TCK means just creating a class which implements an interface and a ServerUnderTestProvider implementation.

See https://github.com/micronaut-projects/micronaut-aws/pull/1538/files#diff-8f69b875a6148983a3f6bbbdb3d29a4883825e685afaeea7a35dd9f3b3d20c72

Moreover, if you are not compliant with a test you can Disable the test see above example.

Honestly, I think it is a good solution it makes trivial to implement it in other modules. See linked PRs.

About creating a testing framework.

The test is in this PR are based on the tests that were in the AWS Module. I had to rewrite them so that they are HTTP server framework agnostic. I wrote helper classes (TestScenario, HTTPResponseAssertion) to remove a lot of duplication and to handle things such as bean pollution. We had a lot of duplication and tests difficult to read and these classes allow you to write HTTP Server tests as:

TestScenario.builder()
.specName("baba")
.request(....)
.assertion()
.run()

But using TestScenario is optional. internally uses the same concepts we use through the framework. HTTP Request, exchanges, assertions of status, body, headers.

@sdelamo
Copy link
Collaborator Author

sdelamo commented Dec 19, 2022

The AWS PR is a good example of consuming the library:

https://github.com/micronaut-projects/micronaut-aws/pull/1538/files#

Right now, it has http-server-tck duplicated as well. But once this gets published in core, I will remove http-server-tck in that PR.

@yawkat
Copy link
Member

yawkat commented Dec 19, 2022

i think it is better to have to do small modifications to the build in dependent modules, if it means we can use normal testing patterns: classes instead of interfaces, automatic discovery instead of registering each test class, maybe even spock, and maybe even being able to click the green arrow in intellij to run a test...

i see that in the aws pr, you disabled an individual test, which is indeed more convenient with your approach. however you could also do this with a normal exclusion rule.

imo you should work with @melix to find a good approach to keep the build as clean as possible but still allow normal testing patterns. (the techempower approach seems hacky, i dont know)

@sdelamo
Copy link
Collaborator Author

sdelamo commented Dec 19, 2022

and maybe even being able to click the green arrow in intellij to run a test...

If you want to run a single test in your tck. You create a class and class AWSHelloTest implement HelloWorldTest and click the green button. That works fine or even rerun only the failed tests in the TCK.

@sdelamo
Copy link
Collaborator Author

sdelamo commented Dec 19, 2022

, maybe even spock,

I like Spock. However, I think it is easier to maintain and to publish a library based on JUnit than in Spock.

@melix
Copy link
Contributor

melix commented Dec 19, 2022

I agree with @yawkat that we should publish a test suite. It shouldn't really be complicated to do it, and it can use Spock too. Consuming shouldn't be complicated either. Especially if the consumers are only Micronaut projects.

@graemerocher
Copy link
Contributor

Would like to point out that there is one other advantage of using JUnit/Java in that we can run these TCK tests with native image.

@alvarosanchez alvarosanchez removed their request for review December 19, 2022 16:21
@sdelamo sdelamo added this to the 3.8.0 milestone Dec 20, 2022
@sdelamo
Copy link
Collaborator Author

sdelamo commented Dec 20, 2022

if it means we can use normal testing patterns: classes instead of interfaces, automatic discovery instead of registering each test class, maybe even spock, and maybe even being able to click the green arrow in intellij to run a test...

I have changed the PR to use @Suite. Let me know if this addresses your concerns.

@sdelamo sdelamo requested a review from yawkat December 20, 2022 00:58
@sdelamo sdelamo requested a review from melix December 20, 2022 09:30
Copy link
Member

@yawkat yawkat left a comment

Choose a reason for hiding this comment

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

thanks!

import org.junit.jupiter.api.Test;
import java.io.IOException;

@SuppressWarnings({
Copy link
Member

Choose a reason for hiding this comment

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

maybe we can turn of sonar/checkstyle for these modules? we don't use them for spock tests either, they're just gonna be a pita...

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree

"java:S5960", // We're allowed assertions, as these are used in tests only
})
@Experimental
public final class AssertionUtils {
Copy link
Contributor

Choose a reason for hiding this comment

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

This module should be internal

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, other modules may want to use it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, but not outside of Micronaut org

import org.junit.jupiter.api.Test;
import java.io.IOException;

@SuppressWarnings({
Copy link
Contributor

Choose a reason for hiding this comment

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

Agree

"checkstyle:MissingJavadocType",
"checkstyle:DesignForExtension"
})
public class MiscTest {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would separate tests into packages named after it's test scenarios: .filters, .reactive, .form etc

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I agree we could improve how the TCK is structured. We can do this after this his been merged. The tests were ported from AWS, where there was no clear structure.

@sonarcloud
Copy link

sonarcloud bot commented Dec 20, 2022

SonarCloud Quality Gate failed.    Quality Gate failed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 28 Code Smells

92.7% 92.7% Coverage
0.0% 0.0% Duplication

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.

None yet

5 participants