You've probably heard someone say something like, "Writing tests now will speed you up later".
We're currently living that with @BrandGhostAI.
We've been fortunate enough that many of our features are light weight and decoupled -- we can iterate fast without risking breaking things.
However, as we onboard users and listen to feedback, we'll need to shift gears.
Enter xUnit and Testcontainers.
📄 Auto-Generated Transcript ▾
Transcript is auto-generated and may contain errors.
what is up it is Saturday morning I'm real sick um I mean it's not that bad but my sinuses are absolutely brutal I'm coughing a ton I haven't been I've had a cold like this in a long time where I have like a scratchy throat but I'm like I really didn't sleep which sucks um that's the worst part about getting sick now that person's coming pretty quick oops um yeah I'm not commuting to work which is nice but it's uh it's about 8:00 in the morning my wife is uh helping host an event and she needed something dropped off I guess it was an Amazon delivery and she needed um I have no idea what it is but she messaged me and she said hey are you awake like yeah unfortunately I feel like I haven't slept but I'm awake so it's about a 20-
minute drive there and minute righty back so I figured we can get a conversation in kind of chat about what I'm uh what I'm building I think the one of the last videos I was talking about the sort of the the things I'm interested in getting built sort of like selfishly in brand ghost there's a a couple I was talking about like I don't know what a good word is to call them like listeners or like being able to listen to either RSS feeds or like web hooks for stuff getting posted like a YouTube video being up uh uploaded or a blog post going up and then um being able to hook into that somehow and then kind of uh add add relevant content to uh topic streams and you know the example of that is like if I upload a podcast to Spotify I
want to have my Spotify topic stream updated to to handle that so or my blog post I'm not writing blog posts currently just because I'm coding a lot more but I have a topic stream that's for that and I don't yet have a YouTube topic stream but I really should like why don't I have that um and it's just because the amount of YouTube videos I I upload and when I was if I were blogging at the same rate I was I was putting out a blog post almost every day and that would be a pain in the butt to go man manually um add that into a topic stream so that's what I want to go build selfishly because that's sort of the evolution of of brand ghost for my use is that plus um this aggregated social feed that we've been talking about
doing just so I spend less time on social media right so these are things that I want um now what's really cool is that we actually have people people that are using the platform which is good um but it means I have to prioritize like what I'm focused on so uh as we've been kind of building stuff there's been a lot more like testing and production which uh I'm not even a huge fan of doing but some of the stuff that we have to do with some of the social media Integrations especially with like oaf it's like we don't have a choice but to be uh you say an app that's running on a hosted domain because uh they have callbacks that that need to be running on things that aren't just Local Host so some of them work for Local Host like they don't
care and others really care that you have a a domain so no that doesn't mean you have to use production but you need to be hosting somewhere and just to to keep things simplified like you know there's been a lot of stuff we've been able to get away with uh especially with a few users just to be able to kind of run and prod but we're we're already like leaving that territory so um now that we have people using it and people who are like keen on on usability and like for feature requests or like uh small bugs and stuff in the ux like there's people that are paying attention so like we have to be like we have to shift gears immediately right um it's uh it's interesting just kind of going it's not like it was a prototype before but um certainly some
aspects of the user interface like prototype is too strong of a word on one end of the spectrum but like we're like hey we got to get it working we got to get it functional so people can try it and now that they are great we can immediately start incorporating that feedback and do something think about it so it really is like shifting gears to a different level so that's what we've been doing with the UI but the reality is the the back end so which is where I spend most of my time like that's no exception now um and it it sort of has been for a little while because I spend a lot of my time in the back end um you know there's features this Tesla driver is ridiculous not no signaling was like tailgating he just trying to pass and being
an idiot anyway whatever some people suck it's too early for me to get pissed off um is it but yeah the the back end in particular is no exception because the database and when you don't have so like to kind of frame oh man this cop is flying through he's going to go through this red light oh yeah what's going on what's going on get out of his way um the uh when you have these users that are onboarding but they're they're not using the platform there's not a whole lot in the database that they're they're using oh I shouldn't cough from the mic I'm sorry I don't know what I'm going to do about that um not cough I guess so it hasn't been that big of an issue because someone's like onboarding like they're getting registered like there's a couple tables I'm like
hey don't touch those Nick um because you're going to mess something up but there's other tables where I'm like they don't have content that's going out like I can mess around with this stuff to a certain degree and like have a lot of confidence that things are okay but now people are putting a bunch of content in and I'm like that's not okay so um so now it's time to go invest way more heavily into uh like testing infrastructure so it's kind of funny because if you think about it we're now getting a lot of feedback which is super cool this is exactly what we need so how do we execute on that but also make our testing infrastructure more robust and these things kind of seem like they're um counterproductive right because you might be saying well okay if you don't have like automated
tests and you don't have like a test database or you don't have whatever infrastructure like you have to go build that that takes time and um and if you're doing that and that's taking time what about the features you're supposed to be delivering but the good news is I think like we've been we've been in the space like we're all really big on automated tests uh we spent a lot of time like championing test automation different types of coded tests um different ways you can approach that like basically stop looking at testing like it's a barrier and if you don't have the infrastructure for testing uh or your code's not set up in a way to test like basically stop making excuses for it and start looking for um the solutions right like oh I couldn't add tests to this because uh they would be
complicated and take a long time time to run and like we don't have anything for that and it's like well okay like you have options like if you think that's the best way to get the coverage like that'll give you the most confidence go spend time building the thing run it once a week run it nightly like do something um or maybe maybe it's because your code set up in a way that doesn't you test well sorry um it's it's pretty bad and um so we spent a long time doing this kind of thing together and uh there are no strangers to it so like uh over the past couple days as we've been kind of having this realization especially cuz some of the feature requests I'm like from the backend side I'm like I think I know how that would need to work and
like I need to change the database schema to make it work I'm thinking like I'm nervous to go touch the database right and this is like a good sounds kind of funny but it's like a good indicator um for where and why you need to test because there's been a lot of stuff we've been doing where I'm like I'm not nervous I can go touch that I have full confidence at least full confidence it's not going to break something else that's what I should clarify I'm not not full confidence my go is going to work the first time but if I'm testing out a feature like validating it trying to see if it works I can be very confident I'm not going to break other things but some of these things coming up now I'm like I don't have that confidence and we cannot risk
derailing other users so that's a good sign to me about where I need to invest in my testing coverage and uh the style of test that I want to write so in this case it's very similar to what I had going on with meal coach and meal coach had uh uh a lot of complexity in the data layer because of how we were trying to like generate meal plans right so we need to be able to to pull things uh and do a lot of like math to to get macronutrients to fit so if you didn't normalize things properly you'd get like weird results like it might it might work like the the queries run but um your results are all weird like it would be like go eat like you know 20 kg of chicken and you're like that seems like not a good
recipe um and in this case it's a couple of things it's not like math but uh scheduling and the other thing is we have some things like users can change records so if you add content you're allowed to change it so we have operations that are like they can be destructive and that makes me very nervous because if I've messed up a query if I've messed up a wear condition like that can mess things up so as we're building more of these features I'm going okay look like I need to be sure that that these work and not have regressions or anything like that so the database in particular for me is one area that needs like a lot of a lot of love and and coverage so I uh I had some patterns that I really liked with meal coach and we used test
containers for basically spinning up Docker containers for our dependencies and in meal coach we had mongod DB in my SQL why I not not people always ask me but when this comes up and I see a lot of people are like oh definitely I use postgress for everything I'm like I don't know why but I just happen to use MySQL like as a default I don't think I have a good reason um it's always just kind of worked and I'm familiar with it but I don't know maybe postgress makes more sense that's a future conversation but in this case we only have uh MySQL we don't have mongod DB as well like with meal coach and I had um like using xunit and test containers uh able to get functional test set up really fast now the one thing that I never had working that
I really need to sort out is that when you're running tests in visual studio with xunit and you run them in parallel it does something weird like they're in different app domains I think is what's happening and if that sounds like it's weird and you don't understand what I'm saying um the the problem I'm trying to solve is that in order to save on resources because when I had thousands of tests running in parallel per test class is the the level of parallelization okay or level of concurrency I don't know how you would say this so within a test class everything will run sequentially but across test classes the classes will run in parallel and because there were enough tests it meant that it would try to go spin up like hundreds of Docker containers and then it would use all the sources on my
computer and then the test wouldn't run like they would all just start failing because there was literally no resources to do anything and then I would look and I'm like well why the hell are there like a 100 Docker containers trying to to grind away so sorry um so the way that you could approach that is like if it were all in the same process the test running then I could e go add some you know some rate limiting some concurrency limitations and it would be fine nothing to worry about but it's not it's it's across processes um and I I don't actually know if it's across processes or app domains but even in C I can't use a static variable which would I don't like doing but would be shared across it's not so I can't do that so what's what's currently an issue
is and it's not it's not an issue right now but it will become one is if I run all of the test sequentially no problem uh it's slower because they're running sequentially but I don't have this issue of like too many containers being stood up and executed um but um as that scales when I go to run them in parallel I don't yet have a way to limit the concurrency and that'll be an interesting problem to solve so that's one thing that's kind of on my mind it's it's a kind of a low priority but it's like a it's a burning question for me cuz I'm like I haven't answered this before um and then the other thing is that we use we use Aspire and I think a a few of us in the group like we're very new to Aspire so we don't
yet understand all the ways that it can help us and um and the tricky thing is like I'm very confident there must be there must be a way that we can use a Spire with our testing and like standing up local resources but but I don't know what that is so right now it's just test containers but I feel like I'm missing something with a spire and sorry I'm coming up on the the convention center that I have to meet my wife and I have no idea where I'm going so I'm going to be editing this part out so I can have a continuous video clip but mental note for me is I'm talking about a Spire I think this way let's go this way okay um so yeah we have we have a Spire but we're not we're probably not using a Spire in
all the awesome ways that we can use a Spire so it's still like TBD on that because I'm pretty confident that instead of using test containers the way that I am or maybe test containers with a Spire or something but there's a way to get this working more effectively maybe that just bypasses the entire weird problem that I'm facing with the concurrency but anyway we'll cross that bridge later it's one of those things that's like uh personally I'm very interested and curious about how that's going to work but it's not really limiting us or affecting it anyway uh I got to find enjoyment along the way right like some of these things are they're in interesting problems to solve for different ways and for me that's kind of like leveling up my my ability to to functionally testet Applications is like understanding that a little
bit better so that's why I'm very interested in seeing how that'll pan out okay so in particular like what am I looking at now and it is going to be a lot of functional tests uh exercising the database and I started some things off with like so for folks that are watching uh I don't know like obviously I don't know your backgrounds but there's a lot of people that are uh net developers that watch my stuff at least on my main channel on this I have literally no idea but one of the really popular uh om's object relational mappers that's inet is called Entity framework The Entity framework core and um I'm per I'm I'm not a fan of it not because I think it's bad I actually I think it's probably the best thing like just probably is but I find from usability like
I always feel like I'm fighting it and it just means I need to spend more time with it I've talked about this many times before I don't like saying I don't use ntity framework cuz I think it sucks I think it's a a mi problem it's a skill issue on my end so that's just how it is but I I like using a framework called Dapper um and Dapper for me is like I like writing my SQL queries manually like I like seeing them I like being able to tune them you can do that in any Entity framework core now so it's it's not like I have a an excuse but I think there's some just some things around the data context and stuff like there's a little bit too much magic or at least too much too much thought process that I keep finding
myself screwing up with any any framew core I man I'm sorry I'm coughing I can't can't control it now I have a lot of like repository uh design patterns in the code base and they wrap a lot of the the Dapper code so basically it's a layer that will look like from the outside you don't know it's anything to do with uh a database or like which database implementation and then inside it's like SQL queries and Dapper um to be able to go between object types and that's just like how I've WR code for a very long time it's very comfortable for me very familiar not here to say it's the best or the worst or whatever just it's familiar it's how I can be effective um so there's a bunch of that code and really what I need to be able to do now
is just like make sure a lot of that is Rock Solid um and the other thing is that like I can test this is kind of where I'm going with this like the feature development is I can test schema changes locally uh instead of trying to to go change the schema in prod and being like okay like I don't even know if I want to deliver this feature yet I need to experiment with it but how like how do I change the schema to not break things at least in like locally I can go do whatever I want now I can totally obliterate everything and just see if I can get it working and that will allow me going back to what I said earlier that will actually allow me to operate more quickly instead of spending so much time up front on something I
don't even know if I need to go push forward on like I need to prototype it first I can get to development way faster to answering questions about the feasibility of it that doesn't remove the problem of like how do I migrate that will still be a problem but I might not even need to answer that question unless I have it working so I think um I'm kind of looking forward to that and being able to iterate so to give you one example it's a pretty simple one there's been a couple features Big shout out to Ryan Murphy again for the the feedback Ryan's asked for a couple of things and um and it's it's funny like I I you know we love the feedback it doesn't matter if it's critical or if it's just feature requests and stuff but Ryan you know he's uh
I I really appreciate this where it's like hey like sorry for it's it's very Canadian of him but uh you know not trying to be picky like you know not trying to not trying to bother anyone but here's some feedback like know don't for us it's like we don't care we we just want the feedback it's helpful so Brian's asked for a couple things that interestingly enough when I was literally first putting together brand ghost and for context brand ghost started with just the the um the backend server because I was using other tooling to be able to call my server to start doing the post and things like that so when I was designing uh the scheduling so I had the posting part working at least for myself for a lot of things when I was building the scheduling out I was building it
like basically with a lot of extensibility and flexibility in mind because I was trying to make what I was already doing if that makes sense but as I was building it I was like I don't know man like I feel like this is an opportunity that I can actually like simplify things like I was just trying to put in a lot of complexity and I it was like catching myself going I don't think I actually need this but it's funny because a couple of feature requests from Ryan are actually some of these things that I literally CED into the schema uh originally and uh oh I need to make sure my front door is unlocked we have cleaners coming and I locked the front door good thing our our Nest tells us oops okay um so I had already coded these things into the original
schema and then kind of backed them out but I was curious cuz when he was asking I'm like I I wonder if like I wonder if it still works like I'm not using it but I wonder if it still works and sure enough there's at least um at least one of the things so the one I wanted to give you was like scheduling a topic stream to post multiple times in a day that literally works in the schema currently we don't have a user experience to like get you to set it up that way but if I change it in the database I was able to write tests that set things up that way in the data and then and then exercise the code on it and it truly does know how to schedule the things multiple times in a day so it's kind of
funny because I I would have been nervous to go mess around with that in production and then be like I don't know if it's going to work or if it's going to you know cause the query to to crash or something when it's trying to go figure out what to schedule so um just an interesting example of like how I was able to take this feature request and and it all works um I'm just checking again my front door I think they're a little early but I think they usually start at 9:00 and it's still like 20 to 9:00 so that's okay but it's unlocked so that's one feature now he has a couple others and uh again like things that I know that I literally put into the schema and and physically remove from the schema cuz I was like no it's going to
be way too complicated for me to wrap my head around now but um they're valid use cases and and like I like I said I tried to design originally for that type of flexibility so now what's cool is I can mess around locally and just say like okay if I need this schema to look like this let me try it um let me try so the the next example is like if you have a a set schedule for your topic streams and for context a topic stream will post uh at a regular interval on the days you want it's kind of like a weekly schedule okay and you pick the social media platforms that you want your content to go out uh at these times on these days but the platforms are consistent across every point so if you make a topic stream and you
set it to have three of your social media accounts every time that topic stream posts it will always be those three social media accounts if you want other ones other configurations you just make a new topic stream but his ask was like look I just want to set up one and and then configure within the topic stream I want like uh one of the social media accounts to post like at a different interval or only on some dayss so it's like it's less spammy of that type of content on this platform and on some other platform because of the type of content that's more acceptable or the style of content like we can post more frequently there and that's totally valid I've solved this myself by by manually dividing up my content into different streams and then it's not an issue but that's just me
so if that doesn't work well for Ryan or other people then like we should think that through so that means that my schema for how I store your schedule needs to change and it needs to include the the Social account like I need to know that this schedule is specifically for this Social account on this topic stream and that's going to make things kind of interesting my goodness and like one there's a weird usability thing here and the example I want to give you is is this so it's going to be hard to show without a picture but let's pretend you have three pieces of content okay sorry for coughing uh um you have three pieces of content and you have a topic stream with two social accounts you want to change the schedule across those social accounts so Social account one will post twice
per week and Social account two will only post once per week now if we think about the three pieces of content and we think about how a week progresses it's pretty simple scenario social media account one will post you know content a then content B on you know two different days and the social media account 2 will only get through posting one piece of content now depending on if social media account two is posting on the first or the second day which piece of content should it post so it might already sound confusing but should it be posting the same and this is what I think it should probably do should it post the same content that everyone else is posting that day every other social account or should it post the next one that it hasn't posted that it hasn't posted right so does
it does it uniquely have to track which piece of content it has posted or not or does it take the global state of the topic stream and even if you know the other accounts have posted stuff it will just skip over them because it will stay consistent now um and I can see Arguments for both cases because if you um if you're only posting what the other social accounts are posting for that topic stream depend how much content you have you're missing you're missing exposure of that content on that platform right so by the time it by the time it goes to repeat you've basically missed a ton of content that could have been posted there um the the counterargument is like okay but if it's not then it's like kind of weirdly inconsistent when you're posting and maybe that's what you want though like
I don't know so it's it's not it's not that trick trivial even uh outside of like the the schema perspective like truly from a usability kind of thing like I don't know what people uh are expecting there so kind of weird I don't know I don't know what what he has in mind for that or if he's kind of thought through that yet um I know for myself I actually do something kind of like this with Tik Tok and my shorts so I post three short videos a day to Tik Tok and it will go through content much faster so my Tik Tok schedule is completely at a sync with my other short form video content and that's been okay for me that works well but I don't know if I want that on my other social platforms and if that has to be a
configurable option that's going to be it's going to be extremely complicated from like a global scheduling perspective so anyway that feature is it's going to be very complicated uh there's ways to simplify the implementation but the the user experience for that I think is going to be far more complex than than is originally thought like it seems kind of simple on the surface but I don't think it's quite as obvious so that'll be an interesting one to solve cuz I see the value in it but the we have to prioritize usability and if it's too confusing we can't put it in we have to find ways to like to make it not confusing so that's been our experience in the past like when things are confusing people just get frustrated and then they don't use them uh or they try using it it's not as
expected and then they're again frustrated so we will figure it out but I'm home and that is not quite a commute but that's a the code commute for today so take care
Frequently Asked Questions
These Q&A summaries are AI-generated from the video transcript and may not reflect my exact wording. Watch the video for the full context.
- How do you handle feature requests and feedback from users while developing BrandGhost?
- I prioritize incorporating user feedback immediately, especially now that we have people actively using the platform. This means shifting gears from just making things functional to improving usability and fixing small bugs. I appreciate all feedback, whether critical or just feature requests, because it helps guide development and improve the product.
- Why is investing in automated testing infrastructure important for BrandGhost's backend development?
- As more users add content, I can't risk breaking things by making untested changes, especially in the database. Investing in automated tests gives me confidence that new features won't cause regressions or break existing functionality. Although building testing infrastructure takes time, it ultimately speeds up development and reduces risk by allowing me to safely experiment and iterate.
- What challenges do you face when scheduling posts across multiple social media accounts in BrandGhost?
- One challenge is allowing different posting schedules for each social media account within the same topic stream. For example, one account might post twice a week while another posts once. This raises questions about whether each account should post the same content on the same day or track which pieces of content it has posted individually. Balancing this flexibility with usability is complex, and we need to design it so users aren't confused or frustrated.