{"id":25776383,"url":"https://github.com/saynotobugsorg/confidence","last_synced_at":"2025-02-27T06:06:20.178Z","repository":{"id":55460791,"uuid":"523089387","full_name":"saynotobugsorg/confidence","owner":"saynotobugsorg","description":"A declarative Java Assertion Framework","archived":false,"fork":false,"pushed_at":"2025-01-20T17:07:12.000Z","size":753,"stargazers_count":11,"open_issues_count":29,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-22T18:51:23.109Z","etag":null,"topics":["declarative","hacktoberfest","java","testing"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/saynotobugsorg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"saynotobugsorg","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2022-08-09T19:51:30.000Z","updated_at":"2025-01-20T17:05:25.000Z","dependencies_parsed_at":"2023-12-03T00:25:52.582Z","dependency_job_id":"8a5d53a6-392c-4c9b-b641-0b957728ccc7","html_url":"https://github.com/saynotobugsorg/confidence","commit_stats":null,"previous_names":[],"tags_count":80,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saynotobugsorg%2Fconfidence","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saynotobugsorg%2Fconfidence/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saynotobugsorg%2Fconfidence/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saynotobugsorg%2Fconfidence/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saynotobugsorg","download_url":"https://codeload.github.com/saynotobugsorg/confidence/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240987434,"owners_count":19889333,"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":["declarative","hacktoberfest","java","testing"],"created_at":"2025-02-27T06:01:22.765Z","updated_at":"2025-02-27T06:06:20.169Z","avatar_url":"https://github.com/saynotobugsorg.png","language":"Java","funding_links":["https://github.com/sponsors/saynotobugsorg"],"categories":["测试"],"sub_categories":[],"readme":"[![Build](https://github.com/saynotobugsorg/confidence/actions/workflows/main.yml/badge.svg?label=main)](https://github.com/saynotobugsorg/confidence/actions/workflows/main.yml)  \n[![codecov](https://codecov.io/gh/saynotobugsorg/confidence/branch/main/graph/badge.svg?token=3wGxOPmEEc)](https://codecov.io/gh/saynotobugsorg/confidence)  \n[![Confidence](https://img.shields.io/badge/Tested_with-Confidence-800000?labelColor=white)](https://saynotobugs.org/confidence)\n\n# Confidence\n\nA declarative Java Assertion Framework.\n\nConfidence makes it easier to write Java Unit tests that give you great confidence in your code with little effort.\n\n# Note\n\nConfidence is still under development. All parts should be considered subject to change.\n\n# Declarative Testing\n\nDeclarative testing means focusing on the **What** instead of the **How**.\n\nAny unit under test (typically a class) has two aspects:\n* **What** it is meant to do and\n* **How** you have to use it.\n\nThe **How** is, to a large extend, determined by the interface of a class or the signature of a function. In case of mutable classes and non-pure functions the order interactions may also be relevant. In any case though, the **How** is typically very static and, to some extent, also enforced by the compiler. That means we often can use the same methods for testing various implementations of the same type, we just need to provide different data and assert different behavior. That's the **What**. A declarative test leaves the **How** to the test framework and only describes the **What**.\n\n## Example\n\nThe classic non-declarative test of a `Predicate` might look like this:\n\n```java\nassertTrue(new IsEven().test(2));\nassertFalse(new IsEven().test(3));\n```\n\nIt contains interface details like the fact that you call the `test` method and that it returns `true` in case the argument satisfies the `Predicate`.\n\nThe declarative test might look like this\n\n```java\nassertThat(new IsEven(),\n    is(allOf(\n        satsifiedBy(2),\n        not(satisfiedBy(3))\n    )));\n```\n\nIn this case we don't see **how** the instance is tested, we just describe **what** we expect, namely that `2` satisfies the `Predicate` and `3` doesn't.\nAll the method calls and result evaluation are performed by the `satisfiedBy` `Quality`, which can be used for every `Predicate` implementation\n\n## Qualities\n\nIn Confidence, you use [`Quality`](https://github.com/saynotobugsorg/confidence/blob/main/confidence-core/src/main/java/org/saynotobugs/confidence/Quality.java)s to express **what** you expect of the unit under test. As seen above, `Quality`s are composable to express even complex behavior.\nConfidence already provides many `Quality` implementations, but to use its full power you should\nwrite custom `Quality`s for your own types.\n\n# Writing custom `Quality` implementations\n\nConfidence already comes with a number of useful `Quality`s that cover many JDK types.\nYet, it is important to be able to write custom implementations. Ideally you provide\na library with `Qualitiy`s for all types you declare in your own code. That makes it easier for you and others (for instance users of your library) to write tests.\n\n## Composing Qualities\n\nIn many cases you can write a new `Quality` by composing it from already existing ones.\nIn fact, many of the `Quality`s in the `confidence-core` module are just compositions of \nsimpler `Quality`s.\n\n### Example\n\nThis is the implementation of the [`EmptyCharSequence`](https://github.com/saynotobugsorg/confidence/blob/main/confidence-core/src/main/java/org/saynotobugs/confidence/quality/charsequence/EmptyCharSequence.java) `Quality`, that describes `CharSequences`\nand `String` with a length of `0`.\n\n```java\n@StaticFactories(value = \"Core\", packageName = \"org.saynotobugs.confidence.quality\")\npublic final class EmptyCharSequence extends QualityComposition\u003cCharSequence\u003e\n{\n    public EmptyCharSequence()\n    {\n        super(new Satisfies\u003c\u003e(c -\u003e c.length() == 0, new Text(\"\u003cempty\u003e\")));\n    }\n}\n\n```\n\nThis creates a new `Quality` composition based on an existing `Satisfies` `Quality`.\n`Satisfies` takes a `Predicate` that must be satisfied for the `Quality` to be satisfied and a `Description` of the expectation. By default, the fail `Description`\nis the actual value, but `Satisfies` takes an optional argument to create a more adequate fail `Description` for a given actual value.\n\nThe annotation\n\n```\n@StaticFactories(value = \"Core\", packageName = \"org.saynotobugs.confidence.quality\")\n```\nensures a static factory methods like the following is automatically created in a class called `Core`:\n\n```java\npublic static EmptyCharSequence emptyCharSequence() {\n    return new org.saynotobugs.confidence.quality.charsequence.EmptyCharSequence();\n}\n```\n\n## Discoverability of Qualities\n\nWhen it comes to writing tests, finding the right `Quality` can often feel like searching for a needle in a haystack. While some frameworks rely on fluent APIs to ease this process, Confidence takes a different approach.\n\nInstead of a fluent API, Confidence organizes its static factory methods into classes named after the types they describe. This convention simplifies the process of discovering `Quality`s, as your IDE may suggest available options simply by typing out the type you're testing.\n\nFor example, if you're working with an instance of `Iterable` (e.g. an `ArrayList`), you'll find suitable `Quality`s in the `org.saynotobugs.confidence.core.quality.Iterable` class. While this may differ from the exact naming of the type you're testing, it ensures a logical organization that aids in discovery.\n\nHowever, there are cases where a `Quality` doesn't directly correlate to a specific type or serves as an adapter. Currently, Confidence addresses four such scenarios:\n\n* **Compositions**: `Quality`s like `allOf`, `not`, or `has` are grouped under the `Composite` class.\n* **Grammar Improvements**: `Quality`s that enhance grammar, such as `is`, `to`, and `soIt`, reside in the `Grammar` class.\n* **Framework Adapters**: Adapters to other frameworks, such as the Hamcrest adapter `qualifiesAs`, are found in the `Adapter` class.\n* **Non-Java Types**: `Quality`s describing non-Java concepts may reside in a dedicated class, e.g. JSON qualities are housed in the `Json` class.\n\nThis organization ensures that regardless of the type or scenario you're testing, Confidence provides a structured and intuitive approach to discovering and utilizing its `Quality`s.\n\n## Testing Qualities\n\nClassic non-declarative tests often times have a major flaw: the (often times very imperative) test code is not tested itself. After all, you only can trust your production code, when you can trust the test code too.\n\nThe functional ideas Confidence is built upon, makes it easy to test\n`Quality`s and ensure the **how** has full test coverage.\n\nConfidence makes it easy to test a `Quality`. Just describe the expected behavior when you provide instances that are expected to pass and some that are expected to fail the assertion of the `Quality` under test:\n\n```java\nassertThat(new EmptyCharSequence(),    // The Quality under test.\n    new AllOf\u003c\u003e(\n        new Passes\u003c\u003e(\"\"),              // An example that should pass the test.\n        new Fails\u003c\u003e(\" \", \"\\\" \\\"\"),     // Examples that should fail the test …\n        new Fails\u003c\u003e(\"123\", \"\\\"123\\\"\"), // … along with the resulting description.\n        new HasDescription(\"\u003cempty\u003e\")  // The description of the Quality.\n    ));\n}\n```\n\n\n\n# Switching from Hamcrest\n\nAs a Hamcrest user you'll find it easy to switch to Confidence. The core idea is the same: Composable components to describe he expected behavior of your code. In Hamcrest these are called `Matcher`, in Confidence they are called `Quality`.\n\nThere are some significant differences though:\n\n* In case of a mismatch, Hamcrest (for Java) needs to run the `Matcher` again to get a mismatch description, a Confidence `Quality` returns an [`Assessment`](https://github.com/saynotobugsorg/confidence/blob/main/confidence-core/src/main/java/org/saynotobugs/confidence/Assessment.java) that contains the result and a description of the issue (in case the assessment failed).\n* Confidence makes it easier to produce comprehensible descriptions, closer to what Assertj or Google Truth produce, by using composable [Descriptions](https://github.com/saynotobugsorg/confidence/blob/main/confidence-core/src/main/java/org/saynotobugs/confidence/Description.java)\n* In Confidence the `Contains` `Quality` has the same semantics as Java `Collection.contains(Object)`\n* Confidence has out ouf the box support for testing `Quality` implementations.\n\nThere are also some noticeable differences in how some of the core `Quality` implementations are being\ncalled or used. The following table shows the most important ones.\n\n\nGeneral note on matching arrays: arrays (including ones of primitive types) can be matched with matchers to match `Iterable`s decorated with `arrayThat(…)`.\n\n| Hamcrest | Confidence                             |\n|---|----------------------------------------|\n| `contains(...)` | `iterates(...)`                        |\n| `containsInAnyOrder(...)` | `iteratesInAnyOrder(...)`              |\n| `iterableWithSize(...)` | `hasNumberOfElements(...)`             |\n| `hasItem(...)` | `contains(...)`                        |\n| `hasItems(...)` | `containsAllOf(...)`                   |\n| `everyItem(...)` | `eachElement(...)`                     |\n| `sameInstance(...)`, `theInstance(...)` | `sameAs(...)`                          |\n| `matchesRegex(...)`, `matchesPattern(...)` | `matchesPattern(...)`                  |\n| `array(...)` | `arrayThat(iterates(...))`*            |\n| `hasItemInArray(...)` | `arrayThat(contains(...))`*            |\n| `arrayWithSize(...)` | `arrayThat(hasNumberOfElements(...))`* |\n\n*works with arrays of primitive types\n\n## confidence-hamcrest\n\nConfidence provides adapters to use Hamcrest `Matcher`s in Confidence assertions and Confidence `Quality`s where\nHamcrest `Matchers` are required (for instance when working with rest-assured, mockito or awaitlity).\n\nYou can use Hamcrest `Matcher`s with Confidence by including the `confidence-hamcrest` artifact and adapting it with\nthe `matches` adapter `Quality`.\n\n```java\nassertThat(List.of(1,2,5,10,11), matches(hasItem(2)));\n```\n\nThe same module also provides a Hamcrest `Matcher` called `qualifiesAs` to use Confidence `Quality`s in a test\nthat requires a `Matcher`:\n\n```java\nresponse.then().body(\"id\", qualifiesAs(jsonStringOf(object(with(\"foo\", equalTo(\"bar\"))))))\n```\n\n# JUnit Confidence TestEngine\n\nOne of the goals of Confidence is to eliminate any imperative code from unit tests. Unfortunately, with Jupiter you still need to write at least one very imperative `assertThat` statement.\n\nThat's why the `confidence-incubator` module contains an experimental JUnit TestEngine to remove this limitation.\n\nWith the ConfidenceEngine you no longer write statements. Instead, you declare `Assertion`s that are verified when the test runs.\n\nCheck out the [`HasPatchTest`](https://github.com/dmfs/semver/blob/main/semver-confidence/src/test/java/org/dmfs/semver/confidence/HasPatchTest.java) from the [dmfs/semver](https://github.com/dmfs/semver/tree/main) project. It verifies that the `HasPatch` `Quality` is satisfied by certain `Version`s (at present the naming has diverged a bit).\n\n```java\n@Confidence\nclass HasPatchTest\n{\n    Assertion has_patch_int = assertionThat(\n        new HasPatch(5),\n        allOf(\n            passes(mock(Version.class, with(Version::patch, returning(5)))),\n            fails(mock(Version.class, with(Version::patch, returning(4))), \"had patch \u003c4\u003e\"),\n            hasDescription(\"has patch \u003c5\u003e\")\n        )\n    );\n\n    Assertion has_patch_quality = assertionThat(\n        new HasPatch(greaterThan(4)),\n        allOf(\n            passes(mock(Version.class, with(Version::patch, returning(5)))),\n            fails(mock(Version.class, with(Version::patch, returning(4))), \"had patch \u003c4\u003e\"),\n            hasDescription(\"has patch greater than \u003c4\u003e\")\n        )\n    );\n}\n```\n\nThe class is annotated with `@Confidence` to make it discoverable by the `ConfidenceEngine`. \n\nThere are no statements in that test, not even test methods.\nThe test only declares certain `Assertion`s that are verified by the test engine.\n\nAlso, there are no `Before` or `After` hooks. The idea is to make those part of the `Assertion` using composition. For instance, when a test requires certain resources you'd apply the `withResources` decorator like in the following test, that requires a git repository in a temporary directory:\n\n```java\n    Assertion default_strategy_on_clean_repo = withResources(\n        new TempDir(),\n        new Repository(\n            getClass().getClassLoader().getResource(\"0.1.0-alpha.bundle\"),\n           \"main\"),\n\n        (tempDir, repo) -\u003e assertionThat(\n            new GitVersion(TEST_STRATEGY, new Suffixes(), ignored -\u003e \"alpha\"),\n            maps(repo, to(preRelease(0, 1, 0, \"alpha.20220116T191427Z-SNAPSHOT\")))));\n```\n\nThe `withResources` decorator creates the required resources before the\nassertion is made and cleans up afterward.\n\nThe Confidence Engine is still in an early ideation phase. You're welcome to try it and make suggestions or contributions for improvements.\n\n## Badge\n\nShow visitors of your repository that you use Confidence to test your projects by embedding this badge\n\n[![Confidence](https://img.shields.io/badge/Tested_with-Confidence-800000?labelColor=white)](https://saynotobugs.org/confidence)\n\nPut the following markdown snippet into your README.md file.\n\n```markdown\n[![Confidence](https://img.shields.io/badge/Tested_with-Confidence-800000?labelColor=white)](https://saynotobugs.org/confidence)\n```\n\nNote that the link to https://saynotobugs.org/confidence currently just redirects to https://github.com/saynotobugsorg/confidence this will change in the near future.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaynotobugsorg%2Fconfidence","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaynotobugsorg%2Fconfidence","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaynotobugsorg%2Fconfidence/lists"}