yeah, most unity youtubers are just people hacking away with unity and have no real professional experience and they always dance around the same beginner level topics.... jason is truly a shining gem and im glad i've found him =)
@wandersonrodrigues1235 жыл бұрын
@@teemuleppa3347 For sure!
@carlosegat14594 жыл бұрын
52:30 NSubstitute - mocking, instancing interfaces, setters for props without setters 1:05:20 NSub - method listener 1:20:36 Play Mode test - mocking input
@bigstones842 жыл бұрын
18:10 assemblies setup
@ryanlaseter76262 жыл бұрын
Watching this again, automated testing is the way to go. Do it small, and for things that matter, and you'll be golden.
@BeauIsLoomfraid5 жыл бұрын
have no clue what are you talking about in most videos but i still like to watch you
@IronFreee4 жыл бұрын
Automated tests are a good way to avoid introducing errors on the existing code by adding stuff. But if you really want it to be effective you have to be rigorous and it takes time... I remember a colleague making a flood test on one of the web services of the project to discover the next day that it was a pay per request service :D
@aoberthuer5 жыл бұрын
This is such a great introduction! Coming from a (Enterprise) Java background one instantly recognizes the same principles applied to Unity. Cannot thank you enough for the effort which went into this video.
@Unity3dCollege5 жыл бұрын
Glad it was helpful! :) I'm a big unit testing addict, just spent the day recording more unit testing videos for the course lol and thinking about a couple new nunit features I wanna dig into :)
@lambdaboss55284 жыл бұрын
Extremely helpful, loved it. Thanks a lot. Completely agree about testing being important. If you haven't watched the video here is what it covers: - Why testing is very important for a project. - How to do unit testing in C# only code. - How to mock C# code. - How to mock MonoBehaviour (Unity code) to test it in a unit testing style. - How to use the PlayMode test runner to test MonoBehaviour code directly. The only question is how important is testing? For a very small project it's not important. If you have a bug, you can find it and you can re-write the entire project if needed in a matter of hours. As projects scale, it becomes much more important to have tests to not waste time searching for and fixing bugs. If you have ever written a game, you know how much time you spend debugging and fixing bugs. Consider that to be roughly the time you would save by having good tests, then you can decide whether or not it's worth it. For me it's always worth it on any project that I'll be coding on for more than 2 weeks or so.
@aligdev Жыл бұрын
Great video again, thank you. Please make more videos about testing and tips and tricks :)
@roboking10203 жыл бұрын
This probably goes without saying, but when it comes to doing play mode tests, specifically for scripts that require connections to other components (e.g. Connecting your player movement with a Rigidbody), just make sure you establish those connections in Awake() and NOT in Start() of the script you're testing. Failing to do so will get you a "System.NullReferenceException : Object reference not set to an instance of an object" error when you try to run your tests. I just spent the last 2 days trying to figure out why this was happening until I came back to rewatch this video and saw 1:11:20. I feel like everyone probably knows this, but just in case theres someone else out there like me struggling with this error, give this a shot. Hope it helps. Cheers.
@Sulihin2 жыл бұрын
It took me a while to get around to this, but it was great. I'm a long time (28 year) mainstream developer who got into programming because I wanted to make games, but never got anywhere with it. Got into Unity in the past year or so and have been trying to figure out how to apply the TDD and general unit testing practice I know from my normal development practice (Java) to Unity. So much of it is about how you design your system, as you show. Thanks for all of the great insight and wisdom!
@michaelberna9872 жыл бұрын
I did not even know that unity had a test runner window! I've been doing all manual testing on my games and other software for the past ten years. Thanks for teaching these other methods.
@WizardsCode4 жыл бұрын
This is awesome, along with almost all of your videos. I love the practical nature of your tutorials and, most importantly, the tiny "if you did it like this it wouldn't work because...". This is not something most tutorials include but this is what makes the difference between knowing how and knowing why. Thank you.
@nguyenphan89845 жыл бұрын
I have subscribed around 40 youtubers, who want to share their Unity knowledge and help others, since I started to learn Unity. Jason, however, is the only channel that I have been checking out for the last 2 years. Awesome job, Jason!
@coderaven11072 жыл бұрын
How to use the current NSubstitute version(took me 4 hours to find out XD) in Unity 2021.3LTS: All information needed are in a stackoverflow question (search for "Importing NSubstitute into Unity Project") and in the microsoft docs (search for "Using .NET 4.x in Unity microsoft learn"). Here is my short summary how it worked for me (Unity 2021.3 LTS, NSubstitute 4.4): 1. Enable the .NET 4.x runtime as described in the paragraph "Enabling the .NET 4.x scripting runtime in Unity" in the microsoft doc link. (Attention! For me it says ".NET Framework" not "NET 4.x" as in the picture) 2. Go to NuGet and download the NSubstitute Package and its dependencies (find them under Dependencies) inserting them into the Unity project as described in the "Add packages from NuGet to a Unity project" paragraph on the microsoft docs link. 3. Add those to your test.asmdef as shown for NSubstitute in this video (Everything mentioned in the accepted answer on the stackoverflow question, except for the System.Threading.Tasks.Extensions.dll should be added there.) I also unchecked everything except Editor in the .dll Files, like Jason does in this video 4. Restart Unity and all Error Messages should be gone. Now you can use the latest NSubstitute version :) Pls upvote, if you found this useful, so more people can see it!
@roboking10203 жыл бұрын
Just watched this after reading about unit testing and tdd in a textbook. Really helps to see it in action (well unit tests at least). It really makes things a lot more clear. Thanks for sharing man.
@charlesmersereau94604 жыл бұрын
Fantastic tutorial. Organized and insightful. One thing I greatly dislike about many tutorials on youtube is when people don't really explain what they're doing or why, which can lead to confusion for the viewer. Not sure if people do it because they're lazy or (I imagine more likely) they don't fully understand it themselves, but it's annoying and unhelpful. Thanks for this!
@SanyaBane3 жыл бұрын
19:55 after I create "Scripts" Assembly Definition inside "Scripts" folder, references to external packages in my project are broken. By external packages I mean things like: TMPro (which is TestMeshPro) UnityEngine.ProBuilder (which is ProBuilder) Pathfinding (which is Astar Pathfinding) Looks like in order to fix it, you need to add ".dll" files of those packages to "Assembly Definition References" of your recently created "Scripts" AssemblyDefinition. In my case, ".dll" which I add were: Unity.TextMeshPro Unity.ProBuilder AstarPathfindingProject
@eToguard2 жыл бұрын
For those of you using Addressables, make sure to add the packages needed. There's more than one, I needed Unity.Addressables and Unity.Addressables.Editor.
@flyingjudgement2 жыл бұрын
This video is a prerequisite it will explain how assemblys work and becomes clear why TMPro or other scripts wont work. kzbin.info/www/bejne/m6DZm5VrrdNrr5I
@michaelberna9872 жыл бұрын
Probably not the best practice, but I ended up creating an assdef in the root of my project instead of my script folder, because I got 150 compilation errors after creating the assembly definition file. I have a good deal of imported asset tools which is what caused this. I tried a bit to squash that at first, but those 150 errors turned out to be more because each time I created an assembly definition file for the asset that needed it, that assembly definition would be missing a few references. It would take all day just to fix that issue, so I cheated.
@SkinnerSpace2 жыл бұрын
After watching this tutorial I became addicted to unit tests
@vinotinto85475 жыл бұрын
Awesome, can't wait to dive into this. Thanks Jason !
@alexchesser52095 жыл бұрын
extract interface and NUnit substitute were mindblowingly new for me :) thanks. edit: OOOOhh... and extract class to new file! edit2: ... and Expression body properties!
@musong3 Жыл бұрын
Really Good lecture for unity unit test!! Thank you!!
@Unity3dCollege Жыл бұрын
You are welcome!
@Tad42day5 жыл бұрын
Great video! The best unity channel on KZbin!
@4evernoobys8565 жыл бұрын
I remember when subscribing to your channel just because a simple tutorial.
@orlovskyconsulting4 жыл бұрын
This is definitely a reference material for running test in Unity3D! Thanks Jason!
@rickloyd82085 жыл бұрын
Just finished first 14 min and I love how you explain everything with real life examples. I tried to get used with unit tests but not for a long... however I still have some tests to check that all game data is in sync and there are no missing resources (since after every branch marge I am afraid that something is broken... and you know it saved release from bug couple of times). Waste time once and benefit in the future...
@rohitdoestech4 жыл бұрын
rider is the best unity editor ever
@Director414 Жыл бұрын
Awesome! Grewat tutorial and walkthrough!
@pgumby2 жыл бұрын
A bit late to the party, but great video Jason, your content is always appreciated.
@absolutedogy3464 жыл бұрын
Great video! lot's of useful information to help me expand my knowledge, but I mean.... it would be easier to watch if you didn't use light mode, idk if it's only me but dark mode is so much easier on the eyes. Still loved the content though!
@andylockhart2575 жыл бұрын
Just worked all the way through this. Absolutely awesome video thanks Jason!
@HadiLePanda5 жыл бұрын
Very awesome format, I now got a general understanding of unit tests and it all made sense to me easily, thank you!
@kozavr Жыл бұрын
17:00 And why the CalculateDamage method is static? What if it must be non-static?
@rgaryfugate5 жыл бұрын
This is huge. Thank you.
@BlueJeebs Жыл бұрын
Awesome guide, doesn't use a powerpoint, gets traight to the point and the length also indicates that htere's more to this than it first seems. Definitely an awesome way of showing off the utility of unit tests, and the workarounds that are needed to properly utilize them in Unity. Thanks for all the info!
@CJKims4 жыл бұрын
20:00 you manually included an assembly definition for your scripts, but what if I have multiple folders in Asset that contains a lot of scripts? You said it was uglier to include them all as global. How do you exactly do that?
@jumpkut4 жыл бұрын
I am wondering the same!
@AlexTheProMacGamer4 жыл бұрын
@@jumpkut I have the same question.
@DustinDustin003 жыл бұрын
As an example: I have a project that has 3 folders under Scripts: GameData, Board, and UI. You create a assembly definition in each of those folders, so you have GameDataAssembly, BoardAssembly, and UIAssembly. Then in my Tests/EditMode, I create the same 3 folders: GameData, Board, UI. In those, I create my test .cs files (usually 1 for each .cs file in the Scripts folder) and in their Assembly Definition Assets, add the needed Assemblies to the Assembly Definition References section. In this case, I generally end up needing the corresponding Assembly + the GameDataAssembly; IE: Tests/EditMode/UI has a UIMode ada that includes a reference to UIAssembly and GameDataAssembly.
@codycanipe4415 Жыл бұрын
Hey Jason, really really great video! I'd really love to see more to unit testing! I got one practical question though: Interfaces can not have concrete implementations of methods. And i can not access the methods of my "normal monobehaviour class" (e.g. character), because i can not instatiate it in the test enviroment. That means in order to access and test a concrete implementation of a method, i need a helper method (either static or from a non-monobehaviour), like you did with DamageCalculator. Now the question. Would you have two methods, one in the class (main method), and on as a helper? But then you would always have to change the helper method as soon as you change the "main method", which means you could forget it and therefore have bugs, despite your test passing. Or would you use helper methods in the first place and use them in the "main class"? I hope my question is understandable :D thanks a lot !
@philippdegasper65093 жыл бұрын
Hey Jason, thanks for your video!
@rutgervd4 жыл бұрын
Great video Jason! I must say the whole NSubstitute part bothers me though, having to use new syntax Substitute.For and .Returns is exactly why I find unit testing such a drag. In every programming language this works differently, and with all these new syntax, how do I know that it is not my tests that erroneous instead of the code that I'm testing? You almost have to start writing unit tests to start testing your unit tests..
@zipzorp88584 жыл бұрын
I love this guys vids.
@rickloyd82085 жыл бұрын
I just got an idea: what's the reason to go to university nowadays when you have personal teacher online, which you can pause any time =) Thanks for a tip: we should not check code, we should check the use case!
@amirishere4 жыл бұрын
Great video thank you! I have a question: How would you inject the playerInput class into player in the real game? right now it wouldn't be initialized right?
@tonyamurray6744 жыл бұрын
It took me a while to figure this out. I ended up doing this in Start() (my interface is ITrialController). If you assign trialCtrl in [Setup], the call to FindObjectOfType will be skipped for the unit tests. When you run the application, trialCtrl will initially be null and FindObjectOfType() will get called. void Start() { Debug.Log("gameController Start()"); if (trialCtrl != null) Debug.Log("trialCtrl already set"); else { Debug.Log("calling FindObjectOfType(typeof(TrialController)"); trialCtrl = (ITrialController)FindObjectOfType(typeof(TrialController)); Debug.Assert(trialCtrl != null, "Problem finding TrialController"); } }
@troyna772 жыл бұрын
Attention: junior programmers and administrators: Document and verify you results through screen capture and your own hand written programming logs with module backups. Why? Even though you are on a team. The other guy on your team is looking out for himself and can easily sabotage your "project" or assignment(especially if they work offsite in another country/state).This could be accidental or on purpose. Learn how to trace your production code in your shop's library. Verify who did what module moves and when. If you don't do your own moves then get to know the operator who does.. Make hard copies. I know from personal experience. No one (even your boss) cares about you. They all want results. But all of the above gives you recourse. And one more thing- recruiters are sharks and don't care about you. Just 2 things college really doesn't teach you.
@constantinbeer12593 жыл бұрын
Your videos are great! Thank you a lot :D
@MudrankitGupta5 ай бұрын
When I add assembly definition (Scripts.asmdef) inside the Scripts folder, loads of missing reference of namespace in the scripts errors show up. These scripts had no such error before adding asmdef. Could you help?
@ziccodx3 жыл бұрын
And if you keep using the DamageCalculator, you might later find out that for mitigation greater than 1 it probably works incorrectly. So input edge cases into the test and freely edit the code thereafter :)
@eduardorabanal28034 жыл бұрын
great tutorial, thanks a lot!
@JoshyHJoshy5 жыл бұрын
Before adding the "scripts" assembly, I do not already have the other two assemblies (UnityEngine.TestRunner & UnityEditor.TestRunner) and they do not appear in the search bar either. What am I missing?
@CanaldoKhal2 жыл бұрын
Great Video! thanks !!
@007walk4 жыл бұрын
Hey Jason, I was wondering how do you do a test, when you using things like UI.Button or Ui.Image in my code. Can this be done in Edit Mode Test?
@michaelberna48362 жыл бұрын
Does anyone know how I can simulate a key press in tests? I would like to create play mode tests for my keyboard shortcuts. For example, I would like to have it simulate a ctrl+s and then check to see if my save menu is set active.
@Spudnic6044 жыл бұрын
What if you have scripts in multiple directories? Maybe scripts you imported from packages?
@darsheelrathore30694 жыл бұрын
For loose coupling we need to use interface, but overtime the amount of "One-Time Interface" used in my project for UNIT TEST becomes numerous. For unit testing is this a good practice ? or We practicing abusive mocking by creating interface of almost every dependency? Actually I'm very new to unit testing, so anything you share in comment will be very beneficial for me and many others who just step into testing world.
@lorensius6054 жыл бұрын
Thank you for the video Jason, I want to ask about how to do Unit Testing on something like random function/value. How do we assert the value when we don't know the outcome?
@EqualToBen5 жыл бұрын
Wow amazing this is great
@pedrobrasil8925 жыл бұрын
At @27:48 the code does't works. The ".Sum" doesn't exist in Values... 😥
@Unity3dCollege5 жыл бұрын
I think you may be missing a using statement at the top for System.Linq;
@coderaven11072 жыл бұрын
Does anyone know if this works the same way in 2021 LTS or if a newer NSubstitute version would be required?
@sajjadkhan92792 жыл бұрын
hi hope you doing well i need your help i have a game having 2 scripts for manifest one is andorid manifes and 2nd is manifest processing i i tried every thing commenting manifest proecess changging manifest file every possible thing i did but when i make abb and i upload it give error of it can't be run above 12 api chance your android exported to true but i haven't seen any activity in manifest that needed to put andorid exported = true what should i do
@SnowTerebi3 жыл бұрын
52:35 NSubstitute
@cylonex-sci-fiadventuregam19092 жыл бұрын
This code will cause overhead. ConvertTo Int is heavy. better do a cast (int). It's also a good pratice to validate input type before returing. you can return 0 if input is wrong. and then do a != 0 check on the object use.
@filipjuza72554 жыл бұрын
I've got a question about private methods. How to test them ? Is it possible without changing the access modifier ?
@deemsameer14013 жыл бұрын
Can I test UI ? Like type in input field then click button and assert the reult ?
@Tasarran3 жыл бұрын
Your mic almost makes it look like you're the feature on MST3K... :D
@justinwhite27255 жыл бұрын
I can't seem to follow the insructions for NSubstitutre. It's not allowing me to add it as an Assembly Definition Reference. I even tried getting the 4.5 version since my project is 4.x targeted. It's not recognizing it as a valid file of that type and won't add to the array. I'm also not getting the 'default' things that you are. You have two items in the Constraints and one already in the Assembly Definitions and I don't have those. Those are both empty. Help?
@justinwhite27255 жыл бұрын
OK looking at it again.. it's an Assembly Reference (not Assembly Defenition Reference) I don't even have that. Also, the dll doesn't look like a puzzle piece like it does in yours. Is this a 2019 specific thing? I'm still on 2018 LTS.
@justinwhite27255 жыл бұрын
Ok ... It seems as though I don't need to do any of that. Seems to recognize the DLL even though it's somewhere else.
@hefhef543214 жыл бұрын
I'm having a problem where I'm getting warnings and failing tests because (according to Unity's console) I'm declaring the Inventory and Item class objects using the "new" keyword Am I supposed to make interfaces for those classes as well?
@hefhef543214 жыл бұрын
Well, I'm still getting those monobehavior warnings about using the "new" keyword but I just found first hand how useful unit testing can be. There was a tiny bug in my code and I would've had more difficulty in finding it if it weren't for the tests telling me "Hey dumbass! You made a booboo somewhere"
@kestutisramulionis23174 жыл бұрын
Hey, is there a way to load a prefab into script?
@СлучващотоСеВБългария5 жыл бұрын
Whenever i create an assembly reference in the scripts folder the whole project crashes huh..
@ryanlaseter76263 жыл бұрын
So I know that you said functional tests are fragile, hard to make, and time expensive? My guess to alleviate that is to break out functional code that acts on things into single testeable parts, then to test the crap out of those? To a certain extend you can't test like UI button placement easilly or, can the player not leave the "correct" play area kind of checks. But doing this breakout would help you the most?
@blue_lobster_4 жыл бұрын
Thanks
@nates97784 жыл бұрын
35:54 I spent over 20 minutes reviewing the code because testing failed, it had to do with the shorthanded if statement at line 12 uggg At least the test results helped point that out though.
@pb94054 жыл бұрын
I know exactly what you're talking about, my IDE didn't format a shorthanded if right and spent wayyy to long to figure it out
@SoaringSimulator4 жыл бұрын
@JasonWeimann , please place your face as a small bottom side sticker into the main starting logo Title so we can recognize that it is actually your youtube video. This alow me to look at your videos more often. Because I recognize that actually are yours.
@Versachiful3 жыл бұрын
None of my tests are showing up in the Test Runner :( Help!
@ZeroSleap4 жыл бұрын
Interesting that,while trying to write the test,you question the game logic and find maybe a flaw you didn't think about before.
@duncanwalker54723 жыл бұрын
the hope for any real scientist
@flem14313 жыл бұрын
is there any benefit to using Asser.AreEqual(x, y) rather than Debug.Assert(y == x)?
@addfill862 жыл бұрын
I think in the first case we will get more information about an exception on a testing error screen
@MordorFishChannel2 жыл бұрын
46:41 Looks like you also need tests that could validate your other tests haha
@ZeroSleap4 жыл бұрын
So i have a question,for sanity's sake,how would i test if a timer finishes at the time it is supposed to finish. The timer of course takes real time to finish,while the test is instanteneous.So how could i make the assert wait for the completion of the timer. The timer is a coroutine.
@menderbug4 жыл бұрын
I think whenever you're dealing with coroutines, you're going to need to write a PlayMode test. Then your test method can be a coroutine itself (as in Jason's final example) and you can just yield return for the appropriate amount of time to check the timer.
@halivudestevez22 жыл бұрын
I am at the point when my game "AI" logic fails, and have to find out why. Now I am refactoring and interested in automated testing, too.
@tr2334 жыл бұрын
I use Xmind to map stuff which i want to learn, so i dont forget what i need to learn.
@SanyaBane3 жыл бұрын
Omg, thanks a lot.
@Pedro5antos_3 жыл бұрын
Great!!
@javiermahana34755 жыл бұрын
Hi right now i'm trying to set up my current proyect in a way that I can be able to test in an easy way. My problem is that because everything that I've done until it's not designed with unit test in mind so I am a little overwhelmed and I don't know how to start. If anyone knows any tip or something that could help me I'd really aprecite it!!!
@alpercaner29235 жыл бұрын
I couldn't understand point of nsubstitute. We mocked the class in our test code and changed to test code much more than a classic mock. I am not sure how to test real monobehaviour class that has complicated logic with nsubstitute.
@Meowzors5 жыл бұрын
The substitute is supposed to setup code not directly related to whatever you're testing. In the example we test damage taken with armor, but we need an inventory in order to have armor. (the CalculateDamage method accesses the character's inventory.) To do that, we create an inventory with the items such as the armor, but the problem is we cant set the character's inventory (the ICharacter.Inventory setter was private). We use NSubstitute to let calls to Character.Inventory to return the inventory we created in the test.
@alpercaner29235 жыл бұрын
@@Meowzors Thanks for the clarification. It's quite helpful!
@Real_MrDk5 жыл бұрын
Hello can you give me suggest that how to learn full unity coding flow
@Unity3dCollege5 жыл бұрын
How experienced are you currently? If you're just getting started, I have this video that should be helpful - kzbin.info/www/bejne/jnWkioZjpr6YbLs I also did this little series that's designed to help people make their first game in about an hour - kzbin.info/www/bejne/eH2VppJsqLipma8
@Unity3dCollege5 жыл бұрын
but if you need something more advanced, let me know what you have in mind and I'll see what i can come up with :)
@Real_MrDk5 жыл бұрын
@@Unity3dCollege Sir I know every basic coding flow in unity 2d but I need more information about 2d coding can you help😊
@Real_MrDk5 жыл бұрын
AS WELL I WANT TO LEARN THAT ACTUALLY WHICH FUNCTION ARE USED FOR... YOU KNOW CAMARA CONTRLING, CINEMACHINE, HOW TO BUILD EDITOR,EACH PHYSICS OF EVERY OBJECT AND WHAT VARIATION OF TECHNICS ARE AVAILABLE MEANS EVERYTHING FOR DEVLOPING GAME
@Real_MrDk5 жыл бұрын
BECAUSE I TAKE THE GAME DEVELOPMENT PROJECT IN COMPUTER ENGINEERING SO AS MY INTEREST I WANT TO LEARN EVERYTHING 😊😊😊😊
@muqali42034 жыл бұрын
Yea.. spent all day refactoring a project ive been working on for the past month. Pretty much broke it and lost all confidence that I knew what I was doing.
@Unity3dCollege4 жыл бұрын
I hope you had source control to go back? Btw it happens to all of us.. i can't count the number of times I've started refactoring, made it worse and had to revert and try again :) Ot never really stops completely, you'll just get much faster at it :)
@syclonusmusic5 жыл бұрын
hi, could you please make a video on how to change the skybox with a timer? i have a space game where the scene first starts in orbit, then 30 seconds in i want to show the view from the planet surface with the sky. i have the IEnumerator code but i cant get it to change. im working in Unity 2018.3.6f1 thanks
@tomibarreche50963 жыл бұрын
Isn't that weird than we can't create unit test for monobehaviour without "cheating" with an external plugin ? Seems odd to me
@openroomxyz4 жыл бұрын
What is assembly definition ? xD
@shadmansudipto72874 жыл бұрын
You could check out infallible code's video on that if you still don't know.
@kozavr Жыл бұрын
I don't want to diminish your work but without explanation how to test non-static methods within a Monobehaviour class you can't call it Everything you need to know about Testing In Unity. But thanks for the video anyway.
@4evernoobys8565 жыл бұрын
First (maybe the last)
@Unity3dCollege5 жыл бұрын
hopefully not the last ;)
@downupblockinc13803 жыл бұрын
Dude I love the tutorials but please man put a limiter on your audio. the mic jump scares me at least once per tutorial
@ethanwasme4307 Жыл бұрын
do you talk so quietly so your ads scare us? when you said mmo developer i didn't think you meant... xD
@FICHEKK5 жыл бұрын
Great video, but I don't agree with your test method naming. According to Microsoft documentation, unit test names should follow the convention MethodName_TestScenario_ExpectedBehavior.
@sagiziv9275 жыл бұрын
Still painful to watch light version… It burns😳😵
@pb94054 жыл бұрын
Does it really or are people just complaining because everyone else complains? When it's day, light mode seems even more readable to me than darkmode