<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Brad Richardson</title>
    <description>The latest articles on Forem by Brad Richardson (@everythingfunct).</description>
    <link>https://forem.com/everythingfunct</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F114524%2F5a5ebd20-a19f-41c8-bfeb-f3a72163351f.jpg</url>
      <title>Forem: Brad Richardson</title>
      <link>https://forem.com/everythingfunct</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/everythingfunct"/>
    <language>en</language>
    <item>
      <title>Like Miracle Grow For Your Garden</title>
      <dc:creator>Brad Richardson</dc:creator>
      <pubDate>Fri, 07 Jun 2019 00:02:27 +0000</pubDate>
      <link>https://forem.com/everythingfunct/like-miracle-grow-for-your-garden-541b</link>
      <guid>https://forem.com/everythingfunct/like-miracle-grow-for-your-garden-541b</guid>
      <description>&lt;p&gt;In the &lt;a href="https://everythingfunctional.wordpress.com/2019/02/10/the-power-of-a-testing-framework/" rel="noopener noreferrer"&gt;last post&lt;/a&gt; I did about the &lt;a href="https://gitlab.com/everythingfunctional/vegetables" rel="noopener noreferrer"&gt;Vegetables&lt;/a&gt; testing framework I developed, I talked about how much of a success it had been. Now I’ve cranked it up to 11. I’ve now got what is effectively QuickCheck level functionality implemented in a Fortran testing framework.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Feverythingfunctional.files.wordpress.com%2F2018%2F11%2Fgiphy-downsized-large.gif%3Fw%3D1100" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Feverythingfunctional.files.wordpress.com%2F2018%2F11%2Fgiphy-downsized-large.gif%3Fw%3D1100" alt="Head Explode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For anyone not familiar with QuickCheck, it is effectively a library for generating random values to use as examples for your tests. But the really useful part is that if it finds an example that causes your test to fail, it then attempts to find the simplest example that causes your test to fail, and reports that to you.&lt;/p&gt;

&lt;p&gt;The simplest example I have is just that an integer should equal itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function checkPassForSameInteger(input) result(result_)
    use Vegetables_m, only: Result_t, assertEquals, assertThat, fail

    class(*), intent(in) :: input
   type(Result_t) :: result_

    type(Result_t) :: example_result

    select type (input)
    type is (integer)
        example_result = assertEquals(input, input)
        result_ = assertThat( &amp;amp;
                example_result%passed(),
                example_result%verboseDescription(.false.))
    class default
        result_ = fail("Expected to get an integer")
    end select
end function checkPassForSameInteger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running just this test now gives the following result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ test_build/vegetable_driver -q -v -f "passes with the same integer"
Running Tests

A total of 1 test cases

All Passed
Test that
    assertEquals with integers
        passes with the same integer
            Passed after 100 examples
A total of 1 test cases containg a total of 1 assertions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, if I change the assert to &lt;code&gt;assertEquals(input, input+1)&lt;/code&gt;, I get the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ test_build/vegetable_driver -q -v -f "passes with the same integer"
Running Tests

A total of 1 test cases

Failed
Test that
    assertEquals with integers
        passes with the same integer
            Fails with the simplest possible example
            Expected to be true
                User Message:
                    [Expected
                             [0]
                     but got
                             [1]]
1 of 1 cases failed
2 of 2 assertions failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, if I change the assert to &lt;code&gt;assertEquals(input, input/2)&lt;/code&gt;, I get the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ test_build/vegetable_driver -q -v -f "passes with the same integer"
Running Tests

A total of 1 test cases

Failed
Test that
    assertEquals with integers
        passes with the same integer
            Found simplest example causing failure
            Expected to be true
                User Message:
                    [Expected
                             [1]
                     but got
                             [0]]
1 of 1 cases failed
2 of 2 assertions failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to use the QuickCheck functionality you need to create a derived type extended from the &lt;code&gt;Generator_t&lt;/code&gt; type. This requires you to implement two functions for it. You need &lt;code&gt;generate&lt;/code&gt;, which takes your generator type as an argument, and produces a random value wrapped in a &lt;code&gt;Generated_t&lt;/code&gt; type. Then you need &lt;code&gt;shrink&lt;/code&gt;, which takes one of your generated values as a &lt;code&gt;class(*)&lt;/code&gt;, and returns a “simpler” value than the one it was given, wrapped in either a &lt;code&gt;ShrunkValue_t&lt;/code&gt; or a &lt;code&gt;SimplestValue_t&lt;/code&gt; to indicate the value can’t be made any simpler.&lt;/p&gt;

&lt;p&gt;I’ve implemented a couple of basic Generators and some helper functions for generating some random values, but for most things, you’ll probably need to create your own. But if you can, and you can specify some properties of your code that should hold for any random value, you can really stress test your code.&lt;/p&gt;

&lt;p&gt;I think at this point I have one of the most feature-full testing frameworks I’ve ever used. And I think in fewer lines of code than any other testing framework I’ve ever seen. Functional programming principles for the win!&lt;/p&gt;

</description>
      <category>fortran</category>
      <category>testing</category>
      <category>framework</category>
    </item>
    <item>
      <title>The Power of a Testing Framework</title>
      <dc:creator>Brad Richardson</dc:creator>
      <pubDate>Sun, 10 Feb 2019 23:11:36 +0000</pubDate>
      <link>https://forem.com/everythingfunct/the-power-of-a-testing-framework-2g94</link>
      <guid>https://forem.com/everythingfunct/the-power-of-a-testing-framework-2g94</guid>
      <description>&lt;p&gt;I am now ready to call Vegetables a huge success. In my &lt;a href="https://everythingfunctional.wordpress.com/2018/11/19/eat-your-vegetables/"&gt;last post&lt;/a&gt; I discussed its design and construction. I am now using it in a project at work. The power and convenience it has brought us is huge.&lt;/p&gt;

&lt;p&gt;The design of Vegetables is such that its use highly encourages writing your tests in a BDD, or at least a specification style. This means that the act of writing tests encourages you to think more explicitly about the requirements of the code you’re writing.&lt;/p&gt;

&lt;p&gt;Now that your test descriptions are written as a requirements specification, the testing framework can report those requirements back to you. We’ve got our tests and our requirements developed as part of a single effort; two birds with one stone.&lt;/p&gt;

&lt;p&gt;Next, with all the information collected by the testing framework as part of running the tests, and the ability to ask it be verbose when reporting the results, means our test suite can effectively generate our V&amp;amp;V report for us. That makes 3 things now that we have gotten out of the single effort of developing our test suite.&lt;/p&gt;

&lt;p&gt;Finally, I added in the ability to ask the framework to run only a subset of the tests. Add this to the verbose outputs and I can get detailed feedback about the piece of code I’m currently working on, without having to wade through the outputs from the rest of the test suite. This shortens and simplifies the feedback cycle and makes TDD, or at least writing the tests very shortly after the code, much more useful. In fact, I put the following script into our repository for everybody to use while developing or debugging.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

DRIVER_PROGRAM="unit_test_build/vegetable_driver"

./shake.sh "${DRIVER_PROGRAM}" &amp;amp;&amp;amp; $DRIVER_PROGRAM -q -v -f "${1}"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I think having this level of power and flexibility from my testing framework is going to be a must have for any project of significant size in the future. It has proved to be too useful to do without. And if one like this doesn’t exist in the language I want to use, I’ll now be confident about creating it, since I’ve now done it for Fortran.&lt;/p&gt;

</description>
      <category>tdd</category>
      <category>testing</category>
      <category>fortran</category>
      <category>framework</category>
    </item>
    <item>
      <title>Eat Your Vegetables</title>
      <dc:creator>Brad Richardson</dc:creator>
      <pubDate>Mon, 19 Nov 2018 02:41:47 +0000</pubDate>
      <link>https://forem.com/everythingfunct/eat-your-vegetables-kad</link>
      <guid>https://forem.com/everythingfunct/eat-your-vegetables-kad</guid>
      <description>&lt;p&gt;About a year ago, I was starting a new project at work using Fortran. For anybody who didn't know, the tools and libraries available to Fortran programmers are few and far between, and not particularly extensible or adaptable. But, being the testing and automation proponent I am, I went looking for a testing framework.&lt;/p&gt;

&lt;p&gt;The only decent, open-source option I found was called fruit. It wasn't particularly well documented, but it purported to be able to find your tests suites at compile time, so you wouldn't have to manually maintain a driver program. It used Rake as a build system, and the Fortran part was contained in a single source file.&lt;/p&gt;

&lt;p&gt;It was unmaintained, and only available from SourceForge, so I figured if I was going to use it, I better take over its maintenance. I grabbed a copy, put it in git, and got to work. I've since cleaned up all the build system components, and even fixed a few of the bugs. But I've made very little changes to the testing framework itself. The framework itself can be found &lt;a href="https://gitlab.com/everythingfunctional/fruit" rel="noopener noreferrer"&gt;here&lt;/a&gt;, and an example hello world type example of how to use it can be found &lt;a href="https://gitlab.com/everythingfunctional/fruit_salad" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Having done all this, I was terribly unsatisfied with it. It's very imperative by nature, makes heavy use of internal state, and it's output leaves a lot to be desired. Having been maintainer of fruit for about a year now, having seen plenty of other testing frameworks in use, and having been bitten by the functional programming bug, I thought, surely I could write a better testing framework. How hard could it be.&lt;/p&gt;

&lt;p&gt;And so, I announce to you now, a new Fortran testing framework: &lt;a href="https://gitlab.com/everythingfunctional/vegetables" rel="noopener noreferrer"&gt;Vegetables&lt;/a&gt;. For a healthier code base, be sure to eat your vegetables. I've still got lots to do, but I believe the foundation is sound and proven at this point. I wanted to explain a bit about how I put it together.&lt;/p&gt;

&lt;p&gt;My first couple attempts (which you can find in the git history if you are truly curious) just didn't work out. It turns out, Fortran just can NOT handle a recursive data structure properly. So I ended up having to link to C++. This isn't particularly ideal, but it was the only way I could get it to work.&lt;/p&gt;

&lt;p&gt;Basically all of the heavy lifting of the framework happens on the C++ side. But all of the interactions happen on the Fortran side by exposing equivalent types and methods. The Fortran types just hold onto a C++ pointer, and pass it back to functions which call the appropriate methods in C++. This means, that unless you really start looking into how the framework is constructed, you won't really be able to tell. A user won't have to concern themselves with dealing with the C++ side of things.&lt;/p&gt;

&lt;p&gt;There is downside to doing things this way. I've basically made a memory leak. The good news, it's memory that under normal circumstances wouldn't be freed until the end of execution anyway. Basically, the whole process of defining your tests builds up a single data structure containing all of them. Then, running the tests creates a second, identically shaped data structure containing all the results. But neither of these go out of scope until the end of the program, so their destructors wouldn't be called until then anyway. The only time you'd even be able to tell is if you're doing something really weird, or testing the testing framework.&lt;/p&gt;

&lt;p&gt;Which brings me to my next point. The framework is fully tested, using itself as the testing framework.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbqowfoocq4tbx7mrkr0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbqowfoocq4tbx7mrkr0.gif" alt="Head Explode" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok, maybe it's not that mind blowing. I'm sure some other testing frameworks have done this. But it was a little tricky trying to do TDD this way. Oh, yeah, I used TDD to build my testing framework. Yeah, that one does deserve a mind explosion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbqowfoocq4tbx7mrkr0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbqowfoocq4tbx7mrkr0.gif" alt="Head Explode" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the early stages of the process the tests weren't really run, they only compiled. But they at least existed and trying to write them was the impetus to say which function or type needed to be written next. I had a pretty good idea for the overall design before I started, which really helped too.&lt;/p&gt;

&lt;p&gt;The basic strategy/design is simply thus: a test is either a test case, or a collection of tests. Hence, a recursive data structure. Then running a test case produces a test result, and running a test collection produces a collection of results; an identically shaped recursive data structure.&lt;/p&gt;

&lt;p&gt;A test collection has a description, and a collection of tests. A test case has a description and a function which returns an assertion result. Assertion results can be &lt;code&gt;.and.&lt;/code&gt;ed together, so a result from a test case can even tell how many assertions were made as a part of it.&lt;/p&gt;

&lt;p&gt;Enough of the abstract, how do you use this thing. Pretty simple, actually. You just define your tests like so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fortran"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test_passing_case_behaviors&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Vegetables_m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TestCollection_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCollection_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"a passing test case"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"it is run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"it knows it passed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkCasePasses&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"it has 1 test case"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkNumCases&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"it has 1 passing case"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkNumPassingCases&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"it has no failing case"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkNumFailingCases&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"it's verbose description still includes the given description"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkVerboseDescription&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"it's failure description is empty"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkFailureDescriptionEmpty&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"it knows how many asserts there were"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkNumAsserts&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"it has no failing asserts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkNumFailingAsserts&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"it knows how many asserts passed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkNumPassingAsserts&lt;/span&gt;&lt;span class="p"&gt;)])])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test_passing_case_behaviors&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;given&lt;/code&gt; is a function which takes a description and an array of test collections and returns a test collection. &lt;code&gt;when&lt;/code&gt; is a function which takes a description and an array of test cases and returns a test collection. &lt;code&gt;then&lt;/code&gt; is a function which takes a description and a function, and returns a test case. The function must take no arguments, and return a result from one or more &lt;code&gt;assert&lt;/code&gt; functions. Like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fortran"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkCasePasses&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;example_cases_m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;examplePassingTestCase&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Vegetables_m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;Result_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;TestCase_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;TestCaseResult_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="k"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;.and.&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;assertNot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Result_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result_&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test_case&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCaseResult_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test_result&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="n"&gt;test_case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;examplePassingTestCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;test_result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test_case&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;result_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_result&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;passed&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="ow"&gt;.and.&lt;/span&gt;&lt;span class="n"&gt;assertNot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_result&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkCasePasses&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are also &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;it&lt;/code&gt; functions which take a description and an array of test cases, and description and function, respectively if you don't need full BDD style given-when-then. At the top level, a function &lt;code&gt;testThat&lt;/code&gt; accepts an array of test collections and returns a single test collection. A single subroutine &lt;code&gt;runTests&lt;/code&gt; accepts a test collection as argument, runs it, and reports the results.&lt;/p&gt;

&lt;p&gt;The test specification is reported to the user prior to running the tests, using indentation to signify the nesting of the test collections. Then, once the tests are run, any failures can be reported exactly the same way.&lt;/p&gt;

&lt;p&gt;The result is a composable, pure-functional, testing framework, with a very nice output as shown below, somewhat abbreviated. See if you can figure out what's broken from the results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Running Tests

Test that
    A test collection
        can tell how many tests it has
        includes the given description
        includes the individual test descriptions

...

A total of 100 test cases

Failed

2 of 50 cases failed
2 of 59 assertions failed

Test that
    A test collection
        can tell how many tests it has
            Expected '2' but got '4'
    A test case
        Only has 1 test case
            Expected '1' but got '2'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is still a fair amount of work left to do, but I am now confident that it will work and is something worth using. Check it out &lt;a href="https://gitlab.com/everythingfunctional/vegetables" rel="noopener noreferrer"&gt;here&lt;/a&gt; if you're curious, and feel free to ask any questions you might have or make any suggestions.&lt;/p&gt;

&lt;p&gt;I also have a question for anybody who might consider using this. Would it be worth supporting a way to report all of the assertions that passed? Right now I've only got the mechanics to show all of the test cases, and the results of any failed assertions, but not the passing assertions. It wouldn't be hard to add, I just haven't decided if it would be worth it. What do you guys think?&lt;/p&gt;

&lt;p&gt;EDIT:&lt;/p&gt;

&lt;p&gt;I've actually managed to get the framework working using only Fortran. The data structures and functionality are the same as described above, but there's no more C++ that needs to be linked in, making this a single file drop in for anyone that doesn't want to use the same build system and automation as me.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>fortran</category>
      <category>framework</category>
      <category>contributorswanted</category>
    </item>
  </channel>
</rss>
