{"id":29955013,"url":"https://github.com/foca/protest","last_synced_at":"2025-08-03T17:09:20.103Z","repository":{"id":661352,"uuid":"304283","full_name":"foca/protest","owner":"foca","description":"E PUR SI MUOVE — Now protest lives at http://github.com/matflores/protest :)","archived":false,"fork":false,"pushed_at":"2009-11-20T11:22:51.000Z","size":148,"stargazers_count":21,"open_issues_count":0,"forks_count":7,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-10-20T19:52:43.304Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://rubyprotest.org","language":"Ruby","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/foca.png","metadata":{"files":{"readme":"README.rdoc","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}},"created_at":"2009-09-11T18:02:18.000Z","updated_at":"2023-10-20T19:52:43.305Z","dependencies_parsed_at":"2022-08-16T10:35:22.632Z","dependency_job_id":null,"html_url":"https://github.com/foca/protest","commit_stats":null,"previous_names":[],"tags_count":4,"template":null,"template_full_name":null,"purl":"pkg:github/foca/protest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foca%2Fprotest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foca%2Fprotest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foca%2Fprotest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foca%2Fprotest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/foca","download_url":"https://codeload.github.com/foca/protest/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foca%2Fprotest/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268578914,"owners_count":24273089,"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","status":"online","status_checked_at":"2025-08-03T02:00:12.545Z","response_time":2577,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2025-08-03T17:09:10.993Z","updated_at":"2025-08-03T17:09:20.092Z","avatar_url":"https://github.com/foca.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"= Protest, the simplicity rebel test framework\n\n    require \"protest\"\n\n    Protest.context(\"A user\") do\n      setup do\n        @user = User.new(:name =\u003e \"John Doe\", :email =\u003e \"john@example.org\")\n      end\n\n      test \"has a name\" do\n        assert_equal \"John Doe\", @user.name\n      end\n\n      test \"has an email\" do\n        assert_equal \"john@example.org\", @user.email\n      end\n    end\n\nProtest is a small, simple, and easy-to-extend testing framework for ruby. It\nwas written as a replacement for Test::Unit, given how awful its code is, and\nhow difficult it is to extend in order to add new features.\n\nI believe in minimalistic software, which is easily understood, easy to test,\nand specially, easy to extend for third parties. That's where I'm aiming with\nProtest.\n\n== Get it\n\n    gem install protest\n\nOr\n\n    rip install git://github.com/foca/protest.git v0.2.3\n\n== Setup and teardown\n\nIf you need to run code before or after each test, declare a +setup+ or\n+teardown+ block (respectively.)\n\n    Protest.context(\"A user\") do\n      setup do # this runs before each test\n        @user = User.create(:name =\u003e \"John\")\n      end\n\n      teardown do # this runs after each test\n        @user.destroy\n      end\n    end\n\n+setup+ and +teardown+ blocks are evaluated in the same context as your test,\nwhich means any instance variables defined in any of them are available in the\nrest.\n\nYou can also use +global_setup+ and +global_teardown+ to run code only once per\ntest case. +global_setup+ blocks will run once before the first test is run, and\n+global_teardown+ will run after all the tests have been run.\n\nThese methods, however, are dangerous, and should be used with caution, as\nthey might introduce dependencies between your tests if you don't write\nyour tests properly. Make sure that any state modified by code run in a\n+global_setup+ or +global_teardown+ isn't changed in any of your tests.\n\nAlso, you should be aware that the code of +global_setup+ and +global_teardown+\nblocks isn't evaluated in the same context as your tests and normal\n+setup+/+teardown+ blocks are, so you can't share instance variables between\nthem.\n\n== Nested contexts\n\nBreak down your test into logical chunks with nested contexts:\n\n    Protest.context(\"A user\") do\n      setup do\n        @user = User.make\n      end\n\n      context \"when validating\" do\n        test \"validates name\" do\n          @user.name = nil\n          assert !@user.valid?\n        end\n\n        # etc, etc\n      end\n\n      context \"doing something else\" do\n        # your get the idea\n      end\n    end\n\nAny +setup+ or +teardown+ blocks you defined in a context will run in that\ncontext and in _any_ other context nested in it.\n\n== Pending tests\n\nThere are two ways of marking a test as pending. You can declare a test with no\nbody:\n\n    Protest.context(\"Some tests\") do\n      test \"this test will be marked as pending\"\n\n      test \"this tests is also pending\"\n\n      test \"this test isn't pending\" do\n        assert true\n      end\n    end\n\nOr you can call the +pending+ method from inside your test.\n\n    Protest.context(\"Some tests\") do\n      test \"this test is pending\" do\n        pending \"oops, this doesn't work\"\n        assert false\n      end\n    end\n\n== Custom assertions\n\nBy default Protest bundles all the assertions defined in Test::Unit (it\nliterally requires them), so check its documentation for all the goodness.\n\nIf you want to add assertions, just define methods that rely on +assert+ or\n+assert_block+. The former takes a boolean and an optional error message as\narguments, while the latter takes an optional error message as an argument and\na block. The assertions is considered to fail if the block evaluates to neither\n+false+ nor +nil+.\n\nFor example:\n\n    module AwesomenessAssertions\n      def assert_awesomeness(object)\n        assert object.awesome?, \"#{object.inspect} is not awesome enough\"\n      end\n    end\n\n    class Protest::TestCase\n      include AwesomenessAssertions\n    end\n\nYou could also define rspec-like matchers if you like that style. See\n\u003ctt\u003ematchers.rb\u003c/tt\u003e in the examples directory for an example.\n\n== Reports\n\nProtest can report the output of a test suite in many ways. The library ships\nwith a \u003ctt\u003e:progress\u003c/tt\u003e report, and a \u003ctt\u003e:documentation\u003c/tt\u003e report,\n\u003ctt\u003e:progress\u003c/tt\u003e being the default.\n\n=== Progress report\n\nThis is the default option, but you can force this by calling \n\u003ctt\u003eProtest.report_with(:progress)\u003c/tt\u003e.\n\nThe progress report will output the \"classic\" Test::Unit output of periods for\npassing tests, \"F\" for failing assertions, \"E\" for unrescued exceptions, and \n\"P\" for pending tests, in full color.\n\n=== Documentation report\n\nUse this report by calling \u003ctt\u003eProtest.report_with(:documentation)\u003c/tt\u003e\n\nFor each testcase in your suite, this will output the description of the test\ncase (whatever you provide TestCase.context), followed by the name of each test\nin that context, one per line. For example:\n\n    Protest.context \"A user\" do\n      test \"has a name\"\n      test \"has an email\"\n\n      context \"validations\" do\n        test \"ensure the email can't be blank\"\n      end\n    end\n\nWill output, when run with the \u003ctt\u003e:documentation\u003c/tt\u003e report:\n\n    A user\n    - has a name (Not Yet Implemented)\n    - has an email (Not Yet Implemented)\n\n    A user validations\n    - ensure the email can't be blank (Not Yet Implemented)\n\n(The 'Not Yet Implemented' messages are because the tests have no body. See\n\"Pending tests\", above.)\n\nThis is similar to the specdoc runner in rspec[http://rspec.info].\n\n=== Defining your own reports\n\nThis is really, really easy. All you need to do is subclass Report, and\nregister your subclass by calling +Protest.add_report+. See the\ndocumentation for details, or take a look at the source code for\nProtest::Reports::Progress and Protest::Reports::Documentation.\n\n== Legal\n\nAuthor:: Nicolás Sanguinetti — http://nicolassanguinetti.info\nLicense:: MIT (see bundled LICENSE file for more info)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoca%2Fprotest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffoca%2Fprotest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoca%2Fprotest/lists"}