C
C#13mo ago
Immutable

❔ Tests best practice

Hello I'm interested in learning more about testing in general like unit tests and other kind of tests I try looking at guides online, but they all show really bad examples that are not just not real. I would like to unit test my ASPNet Api's database logic that seems to need mocks, but should controller be tested? Like if we have ProductController with method CreateProduct(Request) do we test this or just logic inside it? Like services/Repos Does the testing of API fall under different kind of tests like E2E testing for frontend
46 Replies
Immutable
Immutable13mo ago
I'm very interested on how we should approach testing one full production system and how should I structure my tests Also I'm confused on how we should test List of results for example if we have a method that fetches something and creates result of tests it seems annoying to test. Also how do we go about testing a third party lib? In general we should not test other libs as it is expected for them to already have been unit tested that I understand, but what if my logic depends on it Like Discord bot in C# I would like to test outputs of my commands I would need to mock these I would be very happy for any additional resource in this thanks.
Pobiega
Pobiega13mo ago
generally controllers are tested as part of your integration tests, not strict unit tests you'll want to look into WebApplicationFactory https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-7.0 to learn more why is this annoying to test? you'd set up mocks or a test database with a known dataset so you know exactly how many items should be returned you then assert that the items returned are the ones you expect. my number one advice for people learning to write tests is to throw Assert.X in the trashcan where it belongs and install FluentAssertions or Shouldly and use their fluent assertion style which is MUCH nicer to work with and also generates MUCH better error messages when the assertions fail
Immutable
Immutable13mo ago
I see thank you for the info I will check it out What about discord bot example I use Dapper not sure if there is in memory integration I'll have to check I would need to create mock implementation of each repository
Pobiega
Pobiega13mo ago
Not as such, but it doesn't have to be. sqlite is an excellent database for testing or use a test container thats the best solution
Immutable
Immutable13mo ago
Ye some sort of test database
Pobiega
Pobiega13mo ago
yep and that way you can use the same database provider and version as you do in production, so you dont get dialect issues regarding the discord bot, it depends heavily on what bot framework you use and how it works.
Immutable
Immutable13mo ago
It would just need some setup and tear down setup
Pobiega
Pobiega13mo ago
yes, and there are libraries/tools to help with that TestContainers being a very common one
Immutable
Immutable13mo ago
Any personal recommendations?
Pobiega
Pobiega13mo ago
regarding what?
Immutable
Immutable13mo ago
Libs for previously mentioned
Pobiega
Pobiega13mo ago
Immutable
Immutable13mo ago
I'll check it out Integration looks very close to E2E with some selenium I guess we do both tests? One for API route and other for web I have react frontend Backend is c#
Pobiega
Pobiega13mo ago
Part of your FE tests could actually run on a complete FE+BE setup and do true E2E testing, sure
Immutable
Immutable13mo ago
Looks bit annoying to http call each route, but I think swagger code generated can help with that
Pobiega
Pobiega13mo ago
I'm a backend engineer thou, so I wouldn't touch selenium or FE at all using WebApplicationFactory to test your actual API routes is important, because you want to test the ASP.NET pipeline with any middleware you have attached and general httpcontext things
Immutable
Immutable13mo ago
Yep I understand Also, where should I place tests ? In solution like Tests folder then Unit, Integration, E2E Do you utilize code gen for http calls ? Testcontair seems nice to do e2e and integrated I can spawn and run all tests then kill it
Pobiega
Pobiega13mo ago
.
├── .gitignore
├── .editorconfig
├── BlaBla.sln
├── README.md
├── src/
│ ├── BlaBla.Api
│ └── BlaBla.Domain
└── tests/
├── BlaBla.Api.Tests
├── BlaBla.Domain.Tests
├── BlaBla.IntegrationTests
└── BlaBla.EndToEndTests
.
├── .gitignore
├── .editorconfig
├── BlaBla.sln
├── README.md
├── src/
│ ├── BlaBla.Api
│ └── BlaBla.Domain
└── tests/
├── BlaBla.Api.Tests
├── BlaBla.Domain.Tests
├── BlaBla.IntegrationTests
└── BlaBla.EndToEndTests
Immutable
Immutable13mo ago
Also, what do you think about deployment? Should all types of tests run before. Same for commit protection
Pobiega
Pobiega13mo ago
commit protection, absolutely not part of CI? yes ie, any pull request needs to pass at least UTs before it can be merged maybe also integration E2E depends on how heavy your tests are you might just run that nightly or something you dont want a 20 minute test period to be initiated for every single commit, as that will 1: be very expensive 2: lower your throughput
Immutable
Immutable13mo ago
Ye
Pobiega
Pobiega13mo ago
we run a nightly with all bells and whistles, and unittests + convention tests on each CI and then devs are supposed to locally run whatever tests are related to their work before submitting a PR, but that often gets skipped to be fair
Immutable
Immutable13mo ago
What would be Api and domain tests If you do not mind explaining
Pobiega
Pobiega13mo ago
well, it was just random project names but the idea is that most solutions are way more than 1 actual project and you want to split your projects/tests in the same way, so you dont have to rebuild the entire app for every tiny change
Immutable
Immutable13mo ago
I split backend and frontend into 2 repository. So test would not be in 1 place I think I should have some kind of mono repo for it
Pobiega
Pobiega13mo ago
no but even just the BE is likely split into more than one project
Pobiega
Pobiega13mo ago
screenshot from workcomputer:
Pobiega
Pobiega13mo ago
each of these have their own test project too, in the testsfolder you can barely see at the top and we have some extra test projects too, like Integration and Convention our E2E tests are not ran by xunit, so we have them elsewhere
Immutable
Immutable13mo ago
I see Any, how would you approach it
Pobiega
Pobiega13mo ago
as I said, depends on the framework if you can easily mock the input and assert on the output, great just do that but if not, you might need to have your registered bot commands actually fire of a simpler command or testable method from another class just so you can test it this would be nasty, so hopefully your framework of choice has decent testability
Immutable
Immutable13mo ago
Probably something with TestContainer
Pobiega
Pobiega13mo ago
? how would that work iirc you can't set up a fake discord and run E2E tests on a discord bot or rather, you probably can but its likely quite complicated
Immutable
Immutable13mo ago
We can use test bot though Testing sharding would probably not happen, though. That sounds too annoying to make I have projects that scales it but that I can probably fake memory objects and test like that fire fake events and messages
Pobiega
Pobiega13mo ago
I've only built a fairly basic discord bot, and I didn't bother testing its commands directly, but rather the custom command dispatcher I built into it this was a few years ago now
Immutable
Immutable13mo ago
The issue I have is that some stuff seems too difficult to properly test. For example, I built a distributed autoscaler that creates containers How do you even test that. My first idea is to create a whole new project to mock discord events I expect. Use test containers env then fo some kind of integration test We can have both full as real as possible test and fake memory test where we mock api that returns container If we only do memory, we can test logic, but expects other mock api to function properly
Pobiega
Pobiega13mo ago
Not everything is easily or sometimes even at all testable. Distributed autoscaler is testable, imho, but hard. You'd need a way to simulate load, and have each node it spins up report some information to a test controller of sorts
Immutable
Immutable13mo ago
How far should I go about testing it for example Should I go as far as really try to replicate nodes Or only logic testing with memory mocks
Pobiega
Pobiega13mo ago
$itdepends
Pobiega
Pobiega13mo ago
super unhelpful answer, but also very true 100% or 99% test coverage is generally speaking a meme its not attainable in any useful way test stuff that is complicated, or gets changed frequently try to find appropriate abstractions
Immutable
Immutable13mo ago
Damn Yea seems for these systems in a small team tests will cost a lot more Like not everyone is testing Devision methods A lot more infrastructure required to test
Pobiega
Pobiega13mo ago
unittests is a good place to start they are usually fast and you can test your core logic if part of your core logic is things like stored procedures etc, you'll need to go a level higher
Immutable
Immutable13mo ago
Yeah, it is better to have something than nothing at all I think I'll start with only being concerned about logic It seems quite time-consuming to test anything that is larger that is just maybe not worth it Idk I think test env can help with this with information I have so far
Pobiega
Pobiega13mo ago
yes
Immutable
Immutable13mo ago
I'll test those like so Ty for your help Really helped me. I'll study more on materials you sent
Accord
Accord13mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server
More Posts