• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

snowhouse/H03-May-2022-2,7342,040

README.mdH A D09-Feb-202012.8 KiB522363

README.md

1snowhouse
2=========
3[![Travis CI Status](https://travis-ci.org/banditcpp/snowhouse.svg?branch=master)](https://travis-ci.org/banditcpp/snowhouse)
4[![AppVeyor Status](https://ci.appveyor.com/api/projects/status/github/banditcpp/snowhouse?branch=master&svg=true)](https://ci.appveyor.com/project/banditcpp/snowhouse)
5
6An assertion library for C++
7
8Snowhouse is a stand-alone assertion framework for C++.
9
10## Usage
11
12```C++
13#include <snowhouse/snowhouse.h>
14
15using namespace snowhouse;
16
17int main()
18{
19  std::cout << "Testing that 23 is 23" << std::endl;
20  AssertThat(23, Is().EqualTo(23));
21
22  try
23  {
24    AssertThat(12, Is().LessThan(11).And().GreaterThan(99));
25  }
26  catch(const AssertionException& ex)
27  {
28    std::cout << "Apparently this failed:" << std::endl;
29    std::cout << ex.GetMessage() << std::endl;
30  }
31
32  return 0;
33}
34```
35
36### Assertions
37
38Snowhouse uses a constraint-based assertion model that is heavily inspired by the
39model used in [NUnit](http://nunit.org/). An assertion in Snowhouse is written
40using the following format:
41
42```cpp
43AssertThat(actual_value, <constraint expression>);
44```
45
46where `<constraint expression>` is an expression that `actual_value` is
47evaluated against when the test is executed.
48
49Constraint expressions come in two basic forms: composite and fluent expressions.
50
51#### Composite Expressions
52
53With composite expressions, you can create compact, powerful expressions that
54combine a set of predefined constraints with ones that you provide yourself.
55
56Example:
57
58```cpp
59AssertThat(length, IsGreaterThan(4) && !Equals(10));
60```
61
62Composite expressions can be any combination of constraints and the
63standard logical C++ operators.
64
65You can also add your own constraints to be used within composite expressions.
66
67#### Fluent Expressions
68
69With fluent expressions, you can create assertions that better convey the intent
70of a test without exposing implementation-specific details.
71Fluent expressions aim to help you create tests that are not just by developers
72for developers, but rather can be read and understood by domain experts.
73
74Fluent expressions also have the ability to make assertions on the elements in a
75container in a way you cannot achieve with composite expressions.
76
77Example:
78
79```cpp
80AssertThat(length, Is().GreaterThan(4).And().Not().EqualTo(10));
81```
82
83### Basic Constraints
84
85#### Equality Constraint
86
87Used to verify equality between actual and expected.
88
89```cpp
90AssertThat(x, Equals(12));
91AssertThat(x, Is().EqualTo(12));
92```
93
94#### EqualityWithDelta Constraint
95
96Used to verify equality between actual and expected,
97allowing the two to differ by a delta.
98
99```cpp
100AssertThat(2.49, EqualsWithDelta(2.5, 0.1));
101AssertThat(2.49, Is().EqualToWithDelta(2.5, 0.1));
102```
103
104#### GreaterThan Constraint
105
106Used to verify that actual is greater than a value.
107
108```cpp
109AssertThat(x, IsGreaterThan(4));
110AssertThat(x, Is().GreaterThan(4));
111```
112
113#### LessThan Constraint
114
115Used to verify that actual is less than a value.
116
117```cpp
118AssertThat(x, IsLessThan(3));
119AssertThat(x, Is().LessThan(3));
120```
121
122#### GreaterThanOrEqualTo Constraint
123
124Used to verify that actual is greater than or equal to a value.
125
126```cpp
127AssertThat(x, IsGreaterThanOrEqualTo(5));
128AssertThat(x, Is().GreaterThanOrEqualTo(5));
129```
130
131#### LessThanOrEqualTo Constraint
132
133Used to verify that actual is less than or equal to a value.
134
135```cpp
136AssertThat(x, IsLessThanOrEqualTo(6));
137AssertThat(x, Is().LessThanOrEqualTo(6));
138```
139
140### Pointer Constraints
141
142Used to check for `nullptr` equality.
143
144```cpp
145AssertThat(x, IsNull());
146AssertThat(x, Is().Null());
147```
148
149Note that this feature is only available for C++11-compliant compilers.
150In this case, the `SNOWHOUSE_HAS_NULLPTR` macro is defined.
151
152### String Constraints
153
154String assertions in Snowhouse are used to verify the values of
155STL strings (`std::string`).
156
157#### Equality Constraints
158
159Used to verify that actual is equal to an expected value.
160
161```cpp
162AssertThat(actual_str, Equals("foo"));
163AssertThat(actual_str, Is().EqualTo("foo"));
164```
165
166#### Contains Constraint
167
168Used to verify that a string contains a substring.
169
170```cpp
171AssertThat(actual_str, Contains("foo"));
172AssertThat(actual_str, Is().Containing("foo"));
173```
174
175#### EndsWith Constraint
176
177Used to verify that a string ends with an expected substring.
178
179```cpp
180AssertThat(actual_str, EndsWith("foo"));
181AssertThat(actual_str, Is().EndingWith("foo"));
182```
183
184#### StartsWith Constraint
185
186Used to verify that a string starts with an expected substring.
187
188```cpp
189AssertThat(actual_str, StartsWith("foo"));
190AssertThat(actual_str, Is().StartingWith("foo"));
191```
192
193#### HasLength Constraint
194
195Used to verify that a string is of the expected length.
196
197```cpp
198AssertThat(actual_str, HasLength(5));
199AssertThat(actual_str, Is().OfLength(5));
200```
201
202### Constraints on Multiline Strings
203
204If you have a string that contains multiple lines, you can use the collection
205constraints to make assertions on the content of that string.
206This may be handy if you have a string that, for instance, represents the
207resulting content of a file or a network transmission.
208
209Snowhouse can handle both Windows (CR+LF) and Unix (LF) line endings.
210
211```cpp
212std::string lines = "First line\r\nSecond line\r\nThird line";
213AssertThat(lines, Has().Exactly(1).StartingWith("Second"));
214```
215
216### Container Constraints
217
218The following constraints can be applied to containers in the standard template library.
219
220#### Contains Constraint
221
222Used to verify that a container contains an expected value.
223
224```cpp
225AssertThat(container, Contains(12));
226AssertThat(container, Is().Containing(12));
227```
228
229#### HasLength Constraint
230
231Used to verify that a container has the expected length.
232
233```cpp
234AssertThat(container, HasLength(3));
235AssertThat(container, Is().OfLength(3));
236```
237
238#### IsEmpty Constraint
239
240Used to verify that a container is empty.
241
242```cpp
243AssertThat(container, IsEmpty());
244AssertThat(container, Is().Empty());
245```
246
247#### All
248
249Used to verify that all elements of a STL sequence container matches an expectation.
250
251```cpp
252AssertThat(container, Has().All().LessThan(5).Or().EqualTo(66));
253```
254
255#### AtLeast
256
257Used to verify that at least a specified amount of elements in a STL sequence
258container matches an expectation.
259
260```cpp
261AssertThat(container, Has().AtLeast(3).StartingWith("foo"));
262```
263
264#### AtMost
265
266Used to verify that at most a specified amount of elements in a STL sequence
267container matches an expectation.
268
269```cpp
270Assert:That(container, Has().AtMost(2).Not().Containing("failed"));
271```
272
273#### Exactly
274
275Used to verify that a STL sequence container has exactly a specified amount
276of elements that matches an expectation.
277
278```cpp
279AssertThat(container, Has().Exactly(3).GreaterThan(10).And().LessThan(20));
280```
281
282#### EqualsContainer
283
284Used to verify that two STL sequence containers are equal.
285
286```cpp
287AssertThat(container1, EqualsContainer(container2));
288AssertThat(container1, Is().EqualToContainer(container2));
289```
290
291##### Predicate functions
292
293You can supply a predicate function or a functor to `EqualsContainer` to
294customize how to compare the elements in the two containers.
295
296With a predicate function:
297
298```cpp
299static bool are_my_types_equal(const my_type& lhs, const my_type& rhs)
300{
301  return lhs.my_val_ == rhs.my_val_;
302}
303
304AssertThat(container1, EqualsContainer(container2, are_my_types_equal));
305```
306
307With a functor as predicate:
308
309```cpp
310struct within_delta
311{
312  within_delta(int delta) : delta_(delta) {}
313
314  bool operator()(const my_type& lhs, const my_type& rhs) const
315  {
316    return abs(lhs.my_val_ - rhs.my_val_) <= delta_;
317  }
318
319private:
320  int delta_;
321};
322
323AssertThat(container1, Is().EqualToContainer(container1, within_delta(1));
324```
325
326### Exceptions
327
328Exception constraints can be used to verify that your code throws the correct exceptions.
329
330#### AssertThrows
331
332`AssertThrows` succeeds if the exception thrown by the call is of the supplied
333type (or one of its subtypes).
334
335```cpp
336AssertThrows(std::logic_error, myObject.a_method(42));
337```
338
339#### Making Assertions on the Thrown Exceptions
340
341If `AssertThrows` succeeds, it will store the thrown exception so that you can
342make more detailed assertions on it.
343
344```cpp
345AssertThrows(std::logic_error, myObject.a_method(42));
346AssertThat(LastException<std::logic_error>().what(), Is().Containing("logic failure"));
347```
348
349The `LastException<>` is available in the scope of the call to `AssertThrows`.
350An exception is not available between specs in order to avoid the result of
351one spec contaminating another.
352
353### Custom Constraints
354
355You can add your own constraints to Snowhouse to create more expressive specifications.
356
357#### Fulfills Constraints
358
359By defining the following matcher
360
361```cpp
362struct IsEvenNumber
363{
364  bool Matches(const int actual) const
365  {
366    return (actual % 2) == 0;
367  }
368
369  friend std::ostream& operator<<(std::ostream& stm, const IsEvenNumber& );
370};
371
372std::ostream& operator<<(std::ostream& stm, const IsEvenNumber& )
373{
374  stm << "An even number";
375  return stm;
376}
377```
378
379You can create the following constraints in Snowhouse:
380
381```cpp
382AssertThat(42, Fulfills(IsEvenNumber()));
383AssertThat(42, Is().Fulfilling(IsEvenNumber()));
384```
385
386Your custom matcher should implement a method called `Matches()` that takes
387a parameter of the type you expect and returns true if the passed parameter
388fulfills the constraint.
389
390To get more expressive failure messages, you should also implement the
391streaming operator as in the example above.
392
393## Getting better output for your types
394
395Whenever Snowhouse prints an error message for a type, it will use the
396stream operator for that type, otherwise it will print "[unsupported type]"
397as a placeholder.
398
399```cpp
400struct MyType { int x; char c; };
401
402AssertThat(myType, Fulfills(MyConstraint());
403```
404
405Will output the following if the constraint fails:
406
407```
408Expected: To fulfill my constraint
409Actual: [unsupported type]
410```
411
412If we add a stream operator:
413
414```cpp
415std::ostream& operator<<(std::ostream& stream, const MyType& a)
416{
417  stream << a.c << a.x;
418  return stream;
419}
420```
421
422the output will be a bit more readable:
423
424```
425Expected: To fulfill my constraint
426Actual: f23
427```
428
429If it is necessary to print an object in a different manner than the
430usual output stream operator provides, for example, to output more detailed
431information, we can use a specialization of the `Stringizer` class template:
432
433```cpp
434namespace snowhouse
435{
436  template<>
437  struct Stringizer<MyType>
438  {
439    static std::string ToString(const MyType& a)
440    {
441      std::stringstream stream;
442      stream << "MyType(x = " << a.x << ", c = " << int(a.c) << "('" << a.c << "'))";
443      return stream.str();
444    }
445  };
446}
447```
448
449with output:
450
451```
452Expected: To fulfill my constraint
453Actual: MyType(x = 23, c = 102('f'))
454```
455
456## Configurable Failure Handlers
457
458You can provide Snowhouse with custom failure handlers, for example to
459call `std::terminate` instead of throwing an exception.
460See `DefaultFailureHandler` for an example of a failure handler.
461You can derive your own macros with custom failure handlers using
462`SNOWHOUSE_ASSERT_THAT` and `SNOWHOUSE_ASSERT_THROWS`.
463See the definitions of `AssertThat` and `AssertThrows` for examples of these.
464Define `SNOWHOUSE_NO_MACROS` to disable the unprefixed macros `AssertThat`
465and `AssertThrows`.
466
467### Example Use Cases
468
469#### Assert Program State
470
471Log an error immediately as we may crash if we try to continue.
472Do not attempt to unwind the stack as we may be inside a destructor
473or `nothrow` function.
474We may want to call `std::terminate`, or attempt to muddle along
475with the rest of the program.
476
477#### Assert Program State in Safe Builds
478
479As above, but only in debug builds.
480
481#### Test Assert
482
483Assert that a test behaved as expected.
484Throw an exception and let our testing framework deal with the test failure.
485
486## Versioning
487
488Snowhouse uses [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html) since
489version 3.0.0.
490The macros `SNOWHOUSE_MAJOR`, `SNOWHOUSE_MINOR` and `SNOWHOUSE_PATCH` are defined
491accordingly and `SNOWHOUSE_VERSION` contains the version string.
492Note that in prior versions `SNOWHOUSE_VERSION` was the only defined macro.
493
494## Contributing
495
496The development of Snowhouse takes place on [GitHub](//github.com/banditcpp/snowhouse).
497
498Snowhouse is licensed under the Boost Software License.
499See LICENSE_1_0.txt for further information.
500
501By making available code for inclusion into Snowhouse (e.g., by opening a
502pull request on GitHub), you guarantee that the code is licensed under the
503same license as Snowhouse.
504
505Please make sure to be consistent with the project's coding style.
506The `.clang-format` file allows easy checking and implementation of the
507coding style.
508
509C++ code should comply to C++98, C++03- and C++11.
510Please use `__cplusplus` guards if you want to use language features of
511a certain C++ version.
512
513## Responsibilities
514
515Snowhouse was originally developed as part of the [Igloo](//github.com/joakimkarlsson/igloo)
516testing framework by [Joakim Karlsson](//github.com/joakimkarlsson).
517It has been extracted to be usable in other contexts, for example,
518[Bandit](//github.com/banditcpp/bandit).
519
520Snowhouse is maintained by [Stephan Beyer](//github.com/sbeyer) since
521[October 2016](//twitter.com/JHKarlsson/status/789332548799332352).
522