{"id":19631358,"url":"https://github.com/amiralles/contest","last_synced_at":"2025-07-18T19:05:51.385Z","repository":{"id":144186866,"uuid":"32356158","full_name":"amiralles/contest","owner":"amiralles","description":"Contest is a minimalist, cross-platform testing framework for .NET.","archived":false,"fork":false,"pushed_at":"2024-06-14T12:15:26.000Z","size":1335,"stargazers_count":3,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-28T07:42:31.923Z","etag":null,"topics":["terminal-based","unit-testing"],"latest_commit_sha":null,"homepage":"","language":"C#","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/amiralles.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"license.md","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":"2015-03-16T22:13:21.000Z","updated_at":"2024-06-14T12:15:29.000Z","dependencies_parsed_at":null,"dependency_job_id":"7d5593cd-022f-4592-b732-797ae6024147","html_url":"https://github.com/amiralles/contest","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/amiralles/contest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amiralles%2Fcontest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amiralles%2Fcontest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amiralles%2Fcontest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amiralles%2Fcontest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amiralles","download_url":"https://codeload.github.com/amiralles/contest/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amiralles%2Fcontest/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265815689,"owners_count":23832990,"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":["terminal-based","unit-testing"],"created_at":"2024-11-11T12:08:47.190Z","updated_at":"2025-07-18T19:05:51.354Z","avatar_url":"https://github.com/amiralles.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Contest\nContest is a minimalist, cross-platform, unit testing framework for .NET. \n\nContest comes bundled with a lightweight console test runner, \nand in contrast with most popular testing frameworks in the .NET space, it's based on conventions, \nso it doesn't require a whole lot of attributes to identify test cases, setups, and so on. Point in case the testing code \nreads almost like plain English. (And, of course, it runs on Linux and Mac as well!)\n\nDown below, you’ll find a couple of examples of how to write tests using a contest. Just add \na reference to **Contest.Core.dll**, and you will be pretty much ready to go.\n\nAs you will see in the examples below, **contest** supports a wide range of assertions and testing styles, \nwhich you can mix and match to meet your preferences. From fluent assertions to BDD (and everything in between), \n**contest** will help you find a style you enjoy while writing tests.\n\n_*Note: While this is working code, it is not production-ready. It might get released in the near future, tough._\n\n\n#### Fluent Assertions\n```cs\n// This using statement enables fluent assertions.\nusing static Contest.Core.Chatty;\nusing _  = System.Action\u003cContest.Core.Runner\u003e;\n\n\n// Some basic math\n_ add_two_numbers = assert =\u003e That(2 + 2).Is(4);\n\n// Login system\n_ when_an_admin_usr_logs_in = assert =\u003e That(usr.IsAdmin).IsTrue();\n\n_ regular_users_shouldnt_have_root_access = assert =\u003e That(regUsr.HasRootAccess).IsFalse();\n\n\n```\n        \n#### BDD API\nFor those who like the BDD approach better, you may want to try the contest's BDD-inspired API.\n\n```cs\nusing static Contest.Core.BDD;\nusing _  = System.Action\u003cContest.Core.Runner\u003e;\n\n\n// Some basic math\n_ add_two_numbers   = expect =\u003e (2 + 2).ToBe(4);\n_ mul_two_numbers   = expect =\u003e (2 * 3).NotToBe(5);\n\n// Login system\n_ when_an_admin_usr_logs_in = expect =\u003e usr.IsAdmin.ToBe(true);\n\n_ regular_users_shouldnt_have_root_access = expect =\u003e regularUsr.HasRootAccess.ToBe(false);\n\n// Alternative syntax. (It's handy to test exceptions and stuff like that).\n_ cant_access_members_on_null_pointers = assert =\u003e {\n    object obj = null;\n\n    // You can go this way\n    Expect(() =\u003e obj.ToString()).ToThrow\u003cNullReferenceException\u003e();\n\n    // or this way\n    Expect(() =\u003e obj.ToString()).ErrMsg(\"Object reference not set to an instance of an object\");\n\n    // or this other way\n    Expect(() =\u003e obj.ToString()).ErrMsgContains(\"reference not set to an instance\");\n}\n\n// You can also use:\n// * ToBeGreatThan\n// * ToBeGreatThanOrEqual\n// * ToBeLessThanOrEqual\n// * ToBeLessThan\n\n// Comming soon:\n// * NotToBeGreatThan\n// * NotToBeGreatThanOrEqual\n// * NotToBeLessThanOrEqual\n// * NotToBeLessThan\n```\n\n\n#### Plain old \"lambda syntax\"\nThis is the original contest's syntax, and it works the same way it always did.\n\n```cs\nusing _  = System.Action\u003cContest.Core.Runner\u003e;\n\n\n/// Basic features.\nclass Contest_101 {\n\n    _ passing_test = assert =\u003e \n        assert.Equal(4, 2 + 2);\n\n    _ failing_test = assert =\u003e\n        assert.Equal(5, 2 + 2);\n\n    _ expected_exception_passing_test = test =\u003e\n        test.ShouldThrow\u003cNullReferenceException\u003e(() =\u003e {\n            object target = null;\n            var dummy = target.ToString();\n            //================^ null reference ex.\n        });\n\n    _ expected_exception_failing_test = test =\u003e\n        test.ShouldThrow\u003cNullReferenceException\u003e(() =\u003e {\n            //It doesn't throws; So it fails.\n        });\n}\n\n// Per fixture setup/teardown.\nclass Contest_102 {\n    // Fixture setup.\n    _ before_each = test =\u003e {\n        User.Create(\"pipe\");\n        User.Create(\"vilmis\");\n        User.Create(\"amiralles\");\n    };\n\n    // Fixture teardown.\n    _ after_each = test =\u003e {\n        User.Reset();\n    };\n\n    // Actual test cases.\n    _ should_find_existing_users = assert =\u003e \n        assert.IsNotNull(User.Find(\"pipe\"));\n\n    _ should_return_null_when_cant_find_users = assert =\u003e \n        assert.IsNull(User.Find(\"not_exists\"));\n\n    _ should_add_new_users = assert =\u003e {\n        User.Create(\"foo\");\n        assert.Equal(4, User.Count());\n    };\n}\n\n// Per test case setup/teardown.\nclass Contest_103 {\n    _ before_echo = test =\u003e \n        test.Bag[\"msg\"] = \"Hello World!\";\n\n    _ after_echo = test =\u003e \n        test.Bag[\"msg\"] = null;\n\n    //actual test.\n    _ echo = test =\u003e \n        test.Equal(\"Hello World!\", Utils.Echo(test.Bag[\"msg\"]));\n}\n\n```\n\n\n\n#### Wanna hack right away\nJust go to https://github.com/amiralles/intro_contest and take Contest for a spin.\n\n\n\n#### Syntax Sugar\nIf you like the lambda approach but also like to write as little code as possible, \nyou can go with the contest's syntax sugar.\n\n```cs\nusing _  = System.Action\u003cContest.Core.Runner\u003e;\n\n// By adding this using statement you have access\n// to the whole constest API thru helper methods.\nusing static Contest.Core.SyntaxSugar;\n\nclass TestSomeSugar {\n    // Instead of writing this:\n    _ passing_test = assert =\u003e \n        assert.Equal(4, 2 + 2);\n\n    // You can write this:\n    _ passing_test = assert =\u003e Equal(4, 2 + 2);\n\n    //*(It is less code and also reads better without the second assert word).\n\n}\n```\n\n#### How to add assembly-level initialization code\n\nSometimes, you need to execute some initialization code before running any test case. With Contest, \nyou can do that by adding a special type to your project. Add a new class called `ContestInit`, \ncreate a `Setup` method, and put the initialization code in it.\n\n```cs\nusing Contest.Core;\n\npublic class ContestInit {\n    void Setup(Runner runner) {\n        runner.Bag[\"album\"] = \"Rock or Bust!\";\n    }\n}\n```\n(*) To avoid false positives or a corrupt state, the Contest will abort the execution if this method fails.\n\n\n#### How to add assembly-level cleanup code\n\nContest also allows you to run code when it finishes running tests. To do this, \nyou must add another *special type* called **ContestClose**. In this case, you'll have to create \na **Shutdown** method and put the cleanup code there.\n\n\n```cs\nusing Contest.Core;\n\npublic class ContestClose {\n    void Shutdown(Runner runner) {\n        // Some cleanup code...\n    }\n}\n```\n\n\\* Keep in mind that these special types are meant for **global (assembly-level) configuration**. If you need _test level_ or _class level_ configuration,\n  use the before/after callbacks instead (as shown in the samples above).\n\n#### How to add class-level initialization code\nUse this technique when you want a piece of code to run once (and only once) before any test within the class.\n*(We've been trying different approaches for this particular feature, but plain old constructors ended up being the best choice.)\n\n```cs\nclass FooTest {\n    public FooTest () {\n        // Your init code goes in here.\n    }\n}\n\n```\n\n#### How to add class-level cleanup code\nJust modify your test class to implement the IDisposable interface and put your cleanup code inside the dispose method.\nContest will execute this method before exiting the program.\n\n```cs\nclass BarTest : IDisposable {\n    public void Dispose() {\n        // Cleanup code in here.\n    }\n}\n\n```\n\n\n\n#### How to install\nObviously, you can clone the repo, build from sources, and get the binaries. But you can also get [contest from nuget](https://www.nuget.org/packages/Contest/)\n\n#### How to run\nThe easiest way to run Contest is by adding _contest.exe_ to your path. Once you've done that, you can go to whatever directory and just execute:\n\n```sh\ncontest run test_cases.dll\n```\n\n#### How to debug test cases\nIf you were using VS + ReSharper or TestDriven.NET or similar tools, \nyou would likely want to set a breakpoint and do some step-by-step debugging when you find a failing test, right?\n\nWell, while contest doesn't have an integrated \"VS experience\", \nyou still have the chance to debug your tests using a **switch** that will freeze the execution and let you attach the VS debugger.\n\nSet a breakpoint as usual, run `contest` using the **-dbg** flag, attach the VS debugger, go back to the console, and hit [Enter].\n\n```bash\n contest run test_cases.dll -dbg\n```\n\nI know, this is far from ideal, but if you are used to step-by-step debugger, this is \"a\" way to do it :)\n\n\n#### Cherry picking\n##### You can use wildcards to ask Contest to filter your fixtures and only run matching tests.\n```bash\ncontest run test.dll *test_name_contains*\ncontest run test.dll test_name_starts_with*\ncontest run test.dll *test_name_ends_with\n```\n\n\n#### How to test your code under different culture settings\nOften times you have to make sure that your code works under different regional settings. Some testing \nframeworks allow you to do that by adding data annotations to your test cases, something like this:\n\n```cs\n[Test]\n[SetCulture(\"es-AR\")]\npublic void FooTest() {\n    // Your culture sensitve test case.\n}\n```\n\nAlthough it works, it's really tedious. With Contest you can achieve the same thing without touching your code. \n\n```\n# To test under es-AR.\ncontest run test.dll * -ci es_AR\n\n# To test under en-US\ncontest run test.dll * -ci en_US\n```\n\nThe **-ci** flag allows you to override the culture that contests will use to run your test cases. So, \nif you set that flag, the whole thing will run under that specific culture.\n\n_Note: You can use wildcards to run just some test cases under a specific culture and leave the rest as is._\n\n```\n# Let's run just the tests defined in the Foo module under es-AR culture settings\ncontest run test.dll *Foo* -ci es_AR\n```\n\n\n#### How to rerun failing tests\nMost test runners come with a handy feature that allows you to filter \nand run only test cases that failed in the previous run. (I used this feature a lot with ReSharper's test runner.) \nYou can do this with contests, too; just add the **-f** flag, and you are all set.\n\n```bash\n contest run test\\_cases.dll -f\n```\n* You can also see failing tests without running them using the **-lf** flag.\n\n```bash\n contest run test\\_cases.dll -lf\n```\n\n\n#### How to look for slow tests\nWhether you are fixing performance issues or just wanna speed up your tests, Contest can tell you where to start. Just run:\n\n```bash\n contest run test/_cases.dll -yslow\n```\n\nThe command above will print a list of test cases sorted by execution time. (Slowest tests first).\nYou can combine this command with less or any similar tool to get the top 10/20 cases that are worth investigating.\n\nYou can also list the fastest tests first. (OK, I don't see a point either, but still...)\n```bash\n contest run test/_cases.dll -yfast\n```\n\n\n#### How to ignore tests using .test\\_ignore file.\n**TODO:\n\n\n#### How to report issues\nThe best way to report an issue is by providing a failing test case. Which is dead simple if you use https://github.com/amiralles/intro_contest\n\n\n**Whether if you have problems using this library, found a bug o wanna a new feature, feel free to contact me. I'll get back to you as soon as I can.**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famiralles%2Fcontest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famiralles%2Fcontest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famiralles%2Fcontest/lists"}