{"id":17067738,"url":"https://github.com/justinamiller/testingtips","last_synced_at":"2025-03-23T09:46:06.707Z","repository":{"id":143244222,"uuid":"238482502","full_name":"justinamiller/TestingTips","owner":"justinamiller","description":"Tips on testing code","archived":false,"fork":false,"pushed_at":"2020-02-05T15:53:38.000Z","size":10,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-28T16:34:49.823Z","etag":null,"topics":["csharp","testing","unittest"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/justinamiller.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-05T15:25:44.000Z","updated_at":"2023-02-06T21:08:41.000Z","dependencies_parsed_at":"2023-04-10T09:01:21.341Z","dependency_job_id":null,"html_url":"https://github.com/justinamiller/TestingTips","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/justinamiller%2FTestingTips","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/justinamiller%2FTestingTips/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/justinamiller%2FTestingTips/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/justinamiller%2FTestingTips/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/justinamiller","download_url":"https://codeload.github.com/justinamiller/TestingTips/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245084610,"owners_count":20558248,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","testing","unittest"],"created_at":"2024-10-14T11:11:31.770Z","updated_at":"2025-03-23T09:46:06.683Z","avatar_url":"https://github.com/justinamiller.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tips for Testing Code\n\n## Basic concept of testing\n\nTesting is more important than shipping. If you have no tests or an\ninadequate amount, then every time you ship code you won't be sure that you didn't break anything. Deciding on what constitutes an adequate amount is up to your team, but having 100% coverage (all statements and branches) is how you achieve very high confidence and developer peace of mind. This means that in addition to having a great testing framework, you also need to use a [good coverage tool](https://docs.microsoft.com/en-us/visualstudio/test/using-code-coverage-to-determine-how-much-code-is-being-tested).\n\nThere's no excuse to not write tests. There's [plenty of good .NET test frameworks](https://github.com/thangchung/awesome-dotnet-core#testing), so find one that your team prefers. When you find one that works for your team, then aim to always write tests for every new feature/module you introduce. If your preferred method is Test Driven Development (TDD), that is great, but the main point is to just make sure you are reaching your coverage goals before launching any feature, or refactoring an existing one.\n\n\n\n## Single concept per test\n\nEnsures that your tests are laser focused and not testing miscellaenous (non-related) things, forces [AAA patern](http://wiki.c2.com/?ArrangeActAssert) used to make your codes more clean and readable.\n\n**Bad:**\n\n```csharp\n\npublic class MakeDotNetGreatAgainTests\n{\n    [Fact]\n    public void HandleDateBoundaries()\n    {\n        var date = new MyDateTime(\"1/1/2015\");\n        date.AddDays(30);\n        Assert.Equal(\"1/31/2015\", date);\n\n        date = new MyDateTime(\"2/1/2016\");\n        date.AddDays(28);\n        Assert.Equal(\"02/29/2016\", date);\n\n        date = new MyDateTime(\"2/1/2015\");\n        date.AddDays(28);\n        Assert.Equal(\"03/01/2015\", date);\n    }\n}\n\n```\n\n**Good:**\n\n```csharp\n\npublic class MakeDotNetGreatAgainTests\n{\n    [Fact]\n    public void Handle30DayMonths()\n    {\n        // Arrange\n        var date = new MyDateTime(\"1/1/2015\");\n\n        // Act\n        date.AddDays(30);\n\n        // Assert\n        Assert.Equal(\"1/31/2015\", date);\n    }\n\n    [Fact]\n    public void HandleLeapYear()\n    {\n        // Arrange\n        var date = new MyDateTime(\"2/1/2016\");\n\n        // Act\n        date.AddDays(28);\n\n        // Assert\n        Assert.Equal(\"02/29/2016\", date);\n    }\n\n    [Fact]\n    public void HandleNonLeapYear()\n    {\n        // Arrange\n        var date = new MyDateTime(\"2/1/2015\");\n\n        // Act\n        date.AddDays(28);\n\n        // Assert\n        Assert.Equal(\"03/01/2015\", date);\n    }\n}\n\n```\n\n## Three laws of TDD\n1. You may not write production code until you have written a failing unit test\n2. You may not write more of a unit test than is sufficient to fail, and compiling is failing\n3. You may not write more production code than is sufficient to pass the currently failing test\n    \n## Keeping Tests Clean\nProblem with this approach – test code could outgrow your prod code and become unmanageable\n\nIs dirty test code better than no test code?\n* Tests must change as the production code changes\n* The dirtier the tests, the harder they are to change\n* Tests can become a liability due to technical debt of the dirtiness\n\nAbandoning test code has the following consequences\n* Production code defects rise\n* Fear of changing code increases\n* Cleaning / refactoring code descreases due to lack of confidence (Code rot!!!)\n\nTest code is as important as production code – it should be treated as a first class citizen and should be as clean as production code.\n\n## Tests Enable the -ilities\n* Tests are what keep your production code flexible, maintainable and reusable.\n* Tests allow you to make changes to code without fear.\n* Tests enable change.\n* Tests enable improving architecture.\n\nWithout tests, your code base rots.\n\n## FIRST\n* **(F)ast** – tests should be fast / run quickly\n* **(I)ndependent** – tests should NOT depend on each other – tests should be able to be run in any order they like\n* **(R)epeatable** – they should be repeatable in ANY environment without need for any specific infrastructure\n* **(S)elf-validating** – they should have a boolean output – pass or fail, nothing else\n* **(T)imely** – they need to be written in a timely fashion – just before the production code is written – ensures they are easy to code against\n\n## Importance\nUnit Tests are as important if not moreso than the production code they’re for becasue they allow you to make changes confidently and without fear. They allow you to mold your code over time to improve flexibility / maintainability.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjustinamiller%2Ftestingtips","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjustinamiller%2Ftestingtips","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjustinamiller%2Ftestingtips/lists"}