❔ question around testing techniques and ressources for it
good evening everyone
i recently started learning more in depth about testing tdd ddd and corresponding frameworks which seems to me the best matching for how i wanna work on my projects
long story short i would like to start here a small discussion around your toughts about tdd and ddd as well as their frameworks and ressources (for learning) for it
currently iam building a sample application using principles of clean architecture around 3 daya ago i heard about tdd and how the red green blue cycle is supposed to work which i really liked in theory at least
today i tried getting that into practice but there are a few issues concerning me:
- missing ressources about E2E testing with web apis (spend 3h searching found nothing useful)
- missing ressources about integrationtesting (spend 2h and found some small things but again nothing really useful or compatible to what iam doing)
- unclear practices about unit testing (what defines a unit what types of dependencies to mock what to fake and what to leave as is)
- except for playwright there seem to be no frameworks for automated UI tests in blazor webassembly i may be wrong there?
last but not least iam eager to take courses or webinars teaching those things in depth so iam also interested in maybe some suggestions around courses or something like that to buy
67 Replies
TDD I have never jived with on a full-application scale, cause it relies way too much on you actually KNOWING what all your requirements are up-front
in my experience, that's rarely true
I imagine it can work rather well in, like, a microservices ecosystem, where you DO have a pretty solid idea of what you need to do, ahead of time, AND where you're working with relatively small scopes
I would very much not recommend it for any kind of UI application
DDD is the kinda thing where basically every real implementation I've seen is awful
or maybe "awful" is exaggerating
but not great
it's supposed to be a paradigm that enforces domain integrity within complex domains, yeah?
like, if my domain includes Accounts and Transactions, I have one
Account
class and all buisness operations that deal with Accounts ultimately funnel through that class
so, all Account edits and save operations and whatnot are methods on the Account
class
and same for transactions
BUT
it's kinda a paradox
it's supposed to help deal with complexity, but the more complex an app is, the more likely that the "everything has to fit into a single box" concept becomes unrealistic
and even harmful
what defines a unit what types of dependencies to mock what to fake and what to leave as isthe straightforward definition is "if there's ANY dependencies you're not mocking, it's an Integration Test" the practical definition is "whatever you think is appropriate" if you want clean, straightforward answers about testing philosophy, you're gonna be disappointed, there aren't many testing is as much an art form as programming is define seams in your application wherever they seem appropriate or useful to you, and then test around the seams, by exercising inputs and measuring outputs the advice doesn't get much more specific than that, without discussing specific scenarios IMO
wouldnt that just mean you have to make partial domain classes in order for it to "fit in the box"?
does that not violate DDD?
now you don't have centralized domain objects
you have different domain objects representing the same domain entity, with at least some amount of duplicated domain logic
well con the consuming side you still deal with 1 single domain class
on the domain side on the other hand you split your concerns into multiple partial classes
to be completely clear, I don't know if that violates DDD or not
but that's how I've seen DDD implemented on multiple occasions
thats interesting but not what i expected to find
welp i guess i gotta be more creative and "out of guidelines" at that point
I could definitely give you some guidelines for things that work well and don't
but there's loooooooooots of different ways to do the same thing, in testing-land
tdd is mostly what i can do because i dont work agile i work with clear instructions right from the start and have very little change in my requirements if any
the questions about, like, WHERE to put your seams, is entirely subjective
ddd sounds more like an "useless overhead" then as iam just a single person
if that really does work for you, then go for it
people who use TDD regularly seem to thoroughly enjoy it
and I can't argue with any approach that makes testing a priority
my opinion as well
but to be sure, just an opinion
my view on tests is that i can well run unit tests and ensure that 100% of the app works
from authorization attributes on controllers up to sending emails and the logic behind every single meditr handler
I don't know if there's a better name for it, but I would describe my preferred architecture as "data flow design"
indeed
100% coverage is generally not a realistic or effective goal
focus on covering your business layer
mainly
what i mean by 100% is not that every possible edge case is covered but that the entire logic is tested that is "system critical"
maybe your data access layer, if you have one
fair enough
my DAL lives inside the application layer as i dislike having entity framework with repositories
depends on what you mean by "repository"
repository pattern that wraps around ef cores db sets
i much rather work directly with the db context than map it around repositories
if you mean
yes, don't do this, this is trash when you're using EF
me, I use "repositories" all the time over EF
in the form of....
i wouldnt do it with generic repositories but yes thats what i generally avoid
btw iam speaking ef as in ef core the original ef is "out of sight" for me
I.E. purpose-built queries that don't much up business logic
cause in my experience, unit testing with EF is an absolute pain in the ass
I do not want EF logic inside my business layer, directly, because it makes testing business logic WAY harder
with testcontainers and docker its not that bad
like, that right there
I don't want to have to spin up docker to test my business logic
not for unit testing
I'd rather just inject a couple specific bits of data directly, as needed, per-test
the reason i avoid repositories is because it takes away the flexibility of using the db context directly... my queries at some points would get massive with the large amounts of using .Include(blah).ThenInclude(blahblah) etc
when done poorly, yes
see above
purpose-built queries
not "here's the set of queries you're allowed to use, everything has to fit into these"
purpose built query nameing could become quite complex tho
instead "if you need to write a data operation to serve the business layer, this is just the place to put it"
true
also what about the unit of work pattern inside the context itself wouldnt you loose that if you use repositories
not sure what you're referring to
if i say for example iam adding a few entries on table X i update a entry on table Y and delete something from table Z if i use the db context this would work all in a single roundtrip but with repositories you would run into the performance problem on larger scale apps that you need most likely 3 roundtrips for that
who says I can't do updates to multiple tables within a single repository method?
because repository methods are sequential as well
you first do the db crap then say savechanges
right
which I can do inside of a repository method
you most likely must do it otherwise db changes other than queries wouldnt get persistent
unless i have absolutely done something wrong
I'm not really following
yes, if I have multiple related entities to insert, I should do all of that before making one final call to
.SaveChangesAsync()
EF will optimize that with a single round-trip, if it canlets take this for example
you first bulk create something (1 db roundtrip)
then you want to query it to return it to the consumer (2nd db roundtrip)
...
and so on
as after every method that "does" something you gotta have a dbcontext.SaveChanges();
exactly
if that's what the higher layer needs, then that's what
BulkCreateAsync()
would return
if I HAVE to do a query to retrieve those bulk-created records, then it's 2 round-trips, regardless
more likely, I would build the results right there in memoryalso what about lazy loading? wouldnt ef core loose the ability to do so when you work with repos as you return direct objects (pass by value) and not a reference?
fuck lazy loading
like, actually
so its a bad feature i see
then eager loading only
if you don't know ahead of time what data you need to load in a query, you haven't modeled your problem well-enough
lazy loading is also problematic on a technical level
it's thread-blocking
oh thats bad
indeed
do you have an example somewhere on github or so where i could take a deeper look on how its done large scale or?
best way to learn is reading others code pretty much
how what's done?
the linking between DAL domain application and presentation layer
what iam missing is something like a "prime example app"
don't really have anything off-hand
ah alright then
so usually you still got 5 projects inside your app
- presentation layer (maybe a web api)
- application layer (entire business logic)
- data access layer (ef core specific stuff)
- domain layer (all entities)
- test projec
I would say that
I would probably consider domain and DAL the same layer
so you have your entities right beside your ef core implementation of the interfaces the application layer provides?
uhhh
yes
except the other way around for the interface
the DAL provides an interface for the app layer to consume
so the app layer is implementing the dal interface? what?
no, the app layer consumes the DAL
the DAL defines what operations it supports
and the app layer calls them
the app layer doesn't define the interface and the DAL implements it
the DAL both defines and implements it
I suppose your way makes more sense, but I'm not sure if that works, mechanically
the thing is if iam referencing the dal to the application layer then why dont i use the dbontext directly?
not using the dbcontext directly is the GOAL
yes but you dont block yourself from it that way
because it makes testing easier in the app layer
uhhh, yes, if I wanted to chose to not follow my own design pattern, nothing's going to stop me
is that not rather true of all design patterns?
it is
so you directly reference the implementation as well as the abstraction
thats an intressting approach
sort of
only the IoC orchestration references the implementation
which is still segmented
I usually put an
.AddXXX(this IServiceCollection services)
extension method in the root of each layer
then the entry point doessame here
i probably should create my own "clean architecture" template one day
I did say earlier I would call my general approach "data flow design" if I had to give it a name
so, it makes sense I see the data layer as the root of everything
and all other layers built on top of it
I've never really considered or tried building the business layer as the root, but like I said, it does make sense the more I think about it
I'm just not sure if there'd be any cyclical dependency issues, or anything like that
I'm gonna have to try that
if you want to i might be able to help with it as well
iam home in around 45mins then i could host a cwm if you want
business layer really just needs to say "here's the data operations I need, please implement them for me"
and then it defines all the data modeling
nah, I've got plenty to do already
alright
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.