{"id":13471824,"url":"https://github.com/vsavkin/guinness","last_synced_at":"2025-10-09T21:48:51.770Z","repository":{"id":16342618,"uuid":"19092391","full_name":"vsavkin/guinness","owner":"vsavkin","description":"A port of the Jasmine testing framework to Dart.","archived":false,"fork":false,"pushed_at":"2016-04-06T23:35:45.000Z","size":173,"stargazers_count":42,"open_issues_count":7,"forks_count":9,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-26T15:42:12.108Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dart","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/vsavkin.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2014-04-24T02:07:43.000Z","updated_at":"2024-10-28T13:41:13.000Z","dependencies_parsed_at":"2022-09-08T01:11:35.761Z","dependency_job_id":null,"html_url":"https://github.com/vsavkin/guinness","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/vsavkin/guinness","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vsavkin%2Fguinness","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vsavkin%2Fguinness/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vsavkin%2Fguinness/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vsavkin%2Fguinness/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vsavkin","download_url":"https://codeload.github.com/vsavkin/guinness/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vsavkin%2Fguinness/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279002051,"owners_count":26083286,"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-10-09T02:00:07.460Z","response_time":59,"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":"2024-07-31T16:00:49.579Z","updated_at":"2025-10-09T21:48:51.739Z","avatar_url":"https://github.com/vsavkin.png","language":"Dart","readme":"# Guinness\n\nGuinness is a port of the Jasmine library to Dart. It is based on the AngularDart implementation of Jasmine.\n\n[![Build Status](https://travis-ci.org/vsavkin/guinness.svg?branch=master)](https://travis-ci.org/vsavkin/guinness)\n\n## Installation\n\nYou can find the Guinness installation instructions [here](http://pub.dartlang.org/packages/guinness#installing).\n\n## Importing the Library\n\n```dart\nimport 'package:guinness/guinness.dart';\n\nmain() {\n  //you specs\n}\n```\n\nIf you are testing a client-side application, and you want to use html matchers, import the `guinness_html` library.\n\n```dart\nimport 'package:guinness/guinness_html.dart';\n\nmain() {\n  guinnessEnableHtmlMatchers();\n  //you specs\n}\n```\n\n## Syntax\n\nGuinness specs are comprised of `describe`, `it`, `beforeEach`, and `afterEach` blocks.\n\n```dart\nimport 'package:guinness/guinness.dart';\n\nmain(){\n  describe(\"syntax\", () {\n    beforeEach(() {\n      print(\"outer before\");\n    });\n\n    afterEach(() {\n      print(\"outer after\");\n    });\n\n    it(\"runs first\", () {\n      print(\"first\");\n    });\n\n    describe(\"nested describe\", () {\n      beforeEach(() {\n        print(\"inner before\");\n      });\n\n      afterEach(() {\n        print(\"inner after\");\n      });\n\n      it(\"runs second\", () {\n        print(\"second\");\n      });\n    });\n  });\n}\n```\n\nThis will print:\n\n    outer before, first, outer after\n    outer before, inner before, second, inner after, outer after\n\n* To exclude a `describe`, change it to `xdescribe`.\n* To exclude an `it`, change it to `xit`.\n* To make a `describe` exclusive, change it to `ddescribe`.\n* To make an `it` exclusive, change it to `iit`.\n\nIf there is an `iit` in your spec files, Guinness will run only `iit`s. In this case `ddescribe`s will be ignored.\n\n\n### Pending Specs\n\nGuinness supports pending describe and it blocks (blocks without a callback).\n\n```dart\ndescribe(\"pending describe\");\nxdescribe(\"pending xdescribe\");\nddescribe(\"pending ddescribe\");\n\nit(\"pending it\");\nxit(\"pending xit\");\niit(\"pending iit\");\n```\n\n## Async\n\nSince Dart has built-in futures, the Guinness framework makes a good use out of them. If you return a future from\n`beforeEach`, `afterEach`, or `it`, the framework will wait for that future to be resolved.\n\nFor instance:\n\n```dart\nbeforeEach(connectToTheDatabase);\n```\n\nwhere `connectToTheDatabase` returns a future.\n\nSimilarly, you can write:\n\n```dart\nafterEach(releaseConnection);\n```\n\nYou can also write async specs using the following technique:\n\n```dart\nit(\"should return an empty list when the database is empty\", () {\n  return queryDatabase().then((results){\n    expect(results).toEqual([]);\n  });\n});\n```\n\nIf a returned future gets rejected, the test fails.\n\n## Expect\n\nThey way you write assertions in Guinness is by using the `expect` function, as follows:\n\n```dart\nexpect(2).toEqual(2);\n```\n\nThese are a few examples:\n\n```dart\nexpect(2).toEqual(2);\nexpect([1,2]).toContain(2);\nexpect(2).toBe(2);\nexpect(()=\u003e throw \"BOOM\").toThrow();\nexpect(()=\u003e throw \"BOOM\").toThrow(\"BOOM\");\nexpect(()=\u003e throw \"Invalid Argument\").toThrowWith(message: \"Invalid\");\nexpect(()=\u003e throw new InvalidArgument()).toThrowWith(anInstanceOf: InvalidArgument);\nexpect(()=\u003e throw new InvalidArgument()).toThrowWith(type: ArgumentException);\nexpect(false).toBeFalsy();\nexpect(null).toBeFalsy();\nexpect(true).toBeTruthy();\nexpect(\"any object\").toBeTruthy();\nexpect(\"any object\").toBeDefined();\nexpect(null).toBeNull();\nexpect(\"not null\").toBeNotNull();\n\nexpect(2).not.toEqual(1);\nexpect([1,2]).not.toContain(3);\nexpect([1,2]).not.toBe([1,2]);\nexpect((){}).not.toThrow();\nexpect(null).not.toBeDefined();\n\nexpect(new DocumentFragment.html(\"\u003cdiv\u003esome html\u003c/div\u003e\"))\n    .toHaveHtml(\"\u003cdiv\u003esome html\u003c/div\u003e\");\n\nexpect(new DocumentFragment.html(\"\u003cdiv\u003esome text\u003c/div\u003e\"))\n    .toHaveText(\"some text\");\n\nexpect(new DivElement()..classes.add('abc'))\n    .toHaveClass(\"abc\");\n\nexpect(new DivElement()..attributes['attr'] = 'value')\n    .toHaveAttribute(\"attr\");\n\nexpect(new DocumentFragment.html(\"\u003cdiv\u003esome html\u003c/div\u003e\"))\n    .not.toHaveHtml(\"\u003cdiv\u003esome other html\u003c/div\u003e\");\n\nexpect(new DocumentFragment.html(\"\u003cdiv\u003esome text\u003c/div\u003e\"))\n    .not.toHaveText(\"some other text\");\n\nexpect(new DivElement()..classes.add('abc'))\n    .not.toHaveClass(\"def\");\n\nexpect(new DivElement()..attributes['attr'] = 'value')\n    .not.toHaveAttribute(\"other-attr\");\n\nfinal select = new SelectElement();\nselect.children\n  ..add(new OptionElement(value: \"1\"))\n  ..add(new OptionElement(value: \"2\", selected: true))\n  ..add(new OptionElement(value: \"3\"));\nexpect(select).toEqualSelect([\"1\", [\"2\"], \"3\"]);\n```\n\nYou can also use unittest matchers, like this:\n\n```dart\nexpect(myObject).to(beValid); //where beValid is a unittest matcher\n```\n\n## Migrating from Unittest\n\nTo make migration from the unittest library to Guinness easier, `expect` supports an optional second argument.\n\n```dart\nexpect(myObject, beValid); //same as expect(myObject).to(beValid);\n```\n\nThis keeps your unittest assertions working, so you can change them one by one.\n\nWhile transitioning you can have both the unittest and guinness libraries imported:\n\n```dart\nimport 'package:unittest/unittest.dart' hide expect;\nimport 'package:guinness/guinness.dart';\n```\n\n## Extending Guinness\n\nIf you are using a lot of custom matchers, and using `expect(object).to(matcher)` is tedious,\nyou can extend the library, as follows:\n\n```dart\nlibrary test_helper;\n\nimport 'guinness.dart' as gns;\nexport 'guinness.dart';\n\nfinal _m = gns.guinness.matchers;\n\nclass CustomExpect extends gns.Expect {\n  CustomExpect(actual) : super(actual);\n\n  toBePositive() =\u003e _m.expect(actual \u003e 0, true, reason: 'is not positive');\n}\n\nCustomExpect expect(actual) =\u003e new CustomExpect(actual);\n```\n\n## Spy\n\nGuinness supports Jasmine-like spy functions:\n\n```dart\nfinal s = guinness.createSpy(\"my spy\");\nexpect(s).not.toHaveBeenCalled();\n\ns(1);\nexpect(s).toHaveBeenCalled();\nexpect(s).toHaveBeenCalledOnce();\nexpect(s).toHaveBeenCalledWith(1);\nexpect(s).toHaveBeenCalledOnceWith(1);\nexpect(s).not.toHaveBeenCalledWith(2);\n\ns(2);\nexpect((){\n  expect(s).toHaveBeenCalledOnce();\n}).toThrow();\n\nexpect((){\n  expect(s).toHaveBeenCalledOnceWith(1);\n}).toThrow();\n```\n\nIn addition, Guinness support spy objects:\n\n```dart\nclass SomeSpy extends SpyObject implements SomeInterface {}\n\n...\n\nfinal s = new SomeSpy();\ns.invoke(1,2);\ns.name;\ns.name = 'some name';\n\nexpect(s.spy(\"invoke\")).toHaveBeenCalled();\nexpect(s.spy(\"get:name\")).toHaveBeenCalled();\nexpect(s.spy(\"set:name\")).toHaveBeenCalled();\n```\n\nAnd:\n\n```dart\nfinal s = new SomeSpy();\ns.spy(\"invoke\").andCallFake((a,b) =\u003e a + b);\n\nexpect(s.invoke(1,2)).toEqual(3);\n```\n\nYou can also use the `mock` and `dart_mocks` libraries with it.\n\n\n## Guinness and Unittest\n\nGuinness supports pluggable backends, but by default runs on top of the unittest library. Which means that if\nunittest.autoStart is set to true, your specs will run automatically.\n\nYou can always initialize specs manually:\n\n```dart\nguinness.initSpecs();\n```\n\nYou can also run the specs, like this:\n\n```dart\nguinness.runSpecs();\n```\n\nUsually, you don't need to worry about it.\n\n## Guinness and Karma\n\nGuinness works with Karma. Just include `initSpecs`, as follows:\n\n```dart\nfiles: [\n  \"test/main1_test.dart\",\n  \"test/main2_test.dart\",\n  \"packages/guinness/init_specs.dart\",\n  {pattern: '**/*.dart', watched: true, included: false, served: true}\n]\n```\n\n## Status\n\nThere are a few things that are still not supported (e.g., handling named parameters in expectations).\n\n## Implementation Details\n\n### Key Ideas\n\nThe main idea is to treat the Jasmine syntax as a domain specific language. Therefore,\nthe implementation clearly  separates such things as: syntax, semantic model, and execution model. Let's quickly look\n  at the benefits this approach provides:\n\n#### The semantic model is separate from the syntax.\n\nThe semantic model consists of It, Describe, Suite, BeforeEach, and AfterEach objects. You can create and analyse\nthem  without using the context-dependent nested Jasmine syntax.\n\n#### The parsing of specs is separate from the execution of specs.\n\nThe library builds a tree of the It, Describe, Suite, BeforeEach, and AfterEach objects first. And after that,\nas a  separate step, executes them. It enables all sorts of preprocessing (e.g., filtering, reordering).\n\n#### Pluggable backends.\n\nSince the library is a DSL, there can be multiple backend libraries actually executing the specs. By default,\nthe  library comes with the unittest backend.\n\n# Contributors\n\n* Google Inc\n* Victor Savkin\n* Victor Berchet\n* Marko Vuksanovic","funding_links":[],"categories":["Testing","测试"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvsavkin%2Fguinness","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvsavkin%2Fguinness","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvsavkin%2Fguinness/lists"}