Structure in flux currently, please see #1195: Proposal to modularize the guardrail repo
root
: Contains tests and nothing elsecodegen
: Codegen core. Defines algebras and default interpreters.sample
: Contains integration tests for generated code. May be generated viaexample
in the sbt console.
- Readability
- Maintainability
- Testability
- Defer effects
- Typesafe accessors for Java function calls
It is difficult to tell if the code generated by the tool is functional and type sound by structure alone. As unit tests are not enough, integration tests actually run guardrail as a CLI tool to generate complete clients and servers, ensuring everything works as expected.
The projects defined at modules/sample-*
contain:
target/generated
: Sources generated byrunScalaExample
orrunJavaExample
src/main
: Support definitions for generated codesrc/test
: Manually written integration tests against the generated code. These tests are run by theruntimeScalaSuite
,runtimeJavaSuite
, or the integrationtestSuite
command.
By running guardrail, then attempting to compile the generated code, then running integration tests against the generated code, we can ensure quality.
Adding new specifications is accomplished by:
- creating a file in
modules/sample/src/main/resources
- adding an entry in
exampleCases
defined inbuild.sbt
. The available flags are largely undocumented, so reading the parser is necessary.
val exampleCases: List[ExampleCase] = List(
ExampleCase(sampleResource("additional-properties.yaml"), "additionalProperties"),
ExampleCase(sampleResource("petstore.json"), "examples").args("--import", "support.PositiveLong"),
ExampleCase(sampleResource("polymorphism-nested.yaml"), "polymorphismNested").frameworks(Set("akka-http", "endpoints", "http4s"))
)
- First argument has to point to the newly added specification file.
sampleResource
looks up the specification inmodules/sample/src/main/resources
- Second argument defines what package to put the specification into (For regression tests,
issues.issue1234
) .args(...)
is variadic, and concatenates the specified args directly to the end of your command.frameworks(...)
is the set of frameworks that this file should be run against
Define your tests in ./modules/sample-*/src/test/scala
make sure to use
imports corresponding the previously defined packageName
Use the runtimeSuite
command inside of an SBT session to run code generation and execute the tests
testSuite
: Compile, test codegen, run sample codegen, compile sample, run tests inside sampleruntimeSuite
: Run guardrail, then run all tests against the generated codecli
: Useful for scripting:sbt 'cli --client ...'
format
: Runs scalafmt against codebasecheckFormatting
: Verifies formatting, run as part of CI against PRsmdoc
: Generate the doc microsite locally
- Scalameta Quasiquotes: https://github.com/scalameta/scalameta/blob/master/notes/quasiquotes.md