SaturnFramework / Saturn

Opinionated, web development framework for F# which implements the server-side, functional MVC pattern
https://saturnframework.org
MIT License
703 stars 108 forks source link

feature request for documentation: add test examples #312

Open draptik opened 2 years ago

draptik commented 2 years ago

As user of this framework I would like some guidance / best practices for writing tests.

What are typical integration or unit tests one might write (with examples in documentation)?

In C# one might consider using the WebApplicationFactory<T> approach.

https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-5.0

Is also reasonable here?

Don said it's ok to mention this tweet: https://twitter.com/dsymetweets/status/1417417949233795082

64J0 commented 2 years ago

This is something I would like to see here too.

64J0 commented 2 years ago

It would also be great if we have docs teaching how to run the tests for the application.

64J0 commented 2 years ago

I have submitted a PR to teach how to run the tests we have available for this repository. I think that you can check the code there in this project to get some inspiration @draptik. Btw, I don't have much experience in this field of testing with .NET, but I would recommend you to take a look at XUnit.

jkone27 commented 2 years ago

i was able to use test application factory in a project, but requires a dummy Program.cs, as it needs to be a reference type, wheras by default Saturn has a Program module (so static no ref)


type TestProgram() = //needs to be ref type! so cannot use with saturn Program module..
    member this.Dummy() = ()

type TestApplicationFactory() =
    inherit WebApplicationFactory<TestProgram>()

    override this.CreateHostBuilder() =
        Program.app // THIS line replicates the whole saturn app which is in Program module (static)

    //member val LoggingEnvironment : IntegrationTestLoggingEnvironment = null with get,set

    override this.ConfigureWebHost(builder) = // any custom config or override
            !builder
                .UseContentRoot(System.IO.Directory.GetCurrentDirectory())
                .UseUrls("http://*:5000/", "http://*:9090/")
                .UseEnvironment("IntegrationTestEnvironment")
                .ConfigureAppConfiguration(fun cfg ->
                    !cfg.AddJsonFile("appsettings.json").AddEnvironmentVariables()
                )
                .ConfigureServices(fun services ->
                    // configure for testing... 
                )

    override this.ConfigureClient(client) =
        base.ConfigureClient(client)
        //client.DefaultRequestHeaders.Add("Authorization", "Bearer X")

and then it can be used like so in integ tests


type ExampleTest(factory: TestApplicationFactory) =

    interface IClassFixture<TestApplicationFactory>

    [<Fact>]
    member this.``Example controller called returns Hello!``() =
        task {

            use client = factory.CreateClient()

            let! response = client.GetAsync("/example")

            !response.EnsureSuccessStatusCode()

            let! content = response.Content.ReadAsStringAsync()

            Assert.Equal("Hello!", content)
        }