Unit test main function: imports itself error - unit-testing

I'm trying to write a (small) executable, setup using Cabal, unit tested using HSpec. Almost all of my code is in a separate module, Library, including the body of main, which I import into my Main module as the run function
-- In src/Hecho.hs
module Main where
import Library(run)
main :: IO ()
main = run
Although the main function is now as short as I think it can be, is there a way I can write a test for it, say to check that it equals the run function, or maybe to test it some other way? The issue is that my spec file defines another Main module, and I don't seem to be able (or at least I can't figure out how) to import anything into it from the other Main module.
For example, if I try the following
-- In test/HechoSpec.hs
module Main where
import Library
import Main
import Test.Hspec
main :: IO ()
main = hspec $ do
-- Test definitions
Then I get the error:
Module imports form a cycle:
module `Main' (test/HechoSpec.hs) imports itself
Is there a way to test the main function?

Updated answer: Apparently the question is how to make sure Library.run is the same as main.
The answer is that it's not possible to do that. main is a value of type IO () and there is no Eq defined for IO actions. For instance, this program does not type check:
main = print "Hello"
foo = main
fooEqualsMain = foo == main

Related

Mock not being called in Jest

Please help me understand Jest mocks.
I've put some dummy functions in a file:
// actions.js
export function f1() {
return 1
}
export function calls_f1() {
f1()
}
And then in my test file I'm trying to understand how to check that a function calls another function:
import * as actions from './actions.js'
describe("MOCKS", () => {
actions.f1 = jest.fn();
actions.calls_f1();
expect(actions.f1).toBeCalled();
});
But the test is failing saying the mock function wasn't called. I've also tried swapping the 2nd and 3rd lines of the test, to no avail.
My jest config is all good, I've actually been doing a bunch of other testing (in this same file) that works.
What am I missing here?
Note: The actual implementation of this (that I'm simplifying greatly here) involves an actions file that includes a public export function fetchStations() that calls a private (or, rather, not exported) export function _downloadStations(). I'm trying to test that _downloadStations() is called.
I'm using import * as actions only for convenience, so I can write that line and then use whatever functions that file exports under actions.whatever() (instead of having to add functions to the import statement when I decide to use them). If import * as actions has some effect I'm not noticing (as implied by brian below) then I certainly don't have to use it and can use import {thisAction, thatAction} from './actions' of course.
This line:
import * as actions from './actions.js'
binds the module exports from actions.js to actions...
...so setting actions.f1 to a mock function replaces the module export for f1...
...but this doesn't affect calls_f1 since it calls f1 directly.
If calls_f1 is changed to call the module export for f1 then it will call the mock function.
There are two ways to make that happen.
One way is to move f1 into its own module.
The other way is to note that ES6 modules "support cyclic dependencies automatically" (a major design goal of ES6 modules) so a module can import its own exports:
actions.js
import * as actions from './actions'; // <= import the module...
export function f1() {
return 1
}
export function calls_f1() {
actions.f1() // <= ...and use it to call f1
}
actions.test.js
import * as actions from './actions.js'
describe('actions', () => {
it('calls_f1 should call f1', () => {
actions.f1 = jest.fn();
actions.calls_f1();
expect(actions.f1).toBeCalled(); // Success!
})
})
Update
OP updated the question to indicate that the function in question is not exported from the module.
In that case it is just an internal implementation detail of the module and cannot be spied on directly.
Testing it would involve testing for the effects that it causes, and not directly spying on it to see if it was called.

Running Boost.Test without main method invocation

I'm trying to test parts of my code. I wrote the following test.h file:
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE(my_test) {
BOOST_CHECK(true);
}
If I run the test, my application's main method is invoked and since the command line arguments are missing, it terminates. I want to just run the test suite as it is and succeed since BOOST_CHECK on true should be a passed test. Once this works, I would add calls to functions from my code base one by one for regression testing. Is this possible to do? If yes, how?
This post suggests adding the following define to the top of the test.h file but it does not work for skipping the main method invocation:
#define BOOST_TEST_NO_MAIN true
BOOST_TEST_NO_MAIN makes Boost.Test omit its own main function, therefore it will fall back to the applications main function.
In you unit tests, do not link the applications main function (do not add the file which contains the main), and let Boost.Test add its own main, which will run all your tests.

Unit testing D library

The built-in unit testing functionality (unittest {...} code blocks) seems to only be activated when running.
How can I activate unit tests in a library with no main function?
This is somewhat related to this SO question, although the accepted answer there deals with a workaround via the main function.
As an example, I would expect unit testing to fail on a file containing only this code:
int foo(int i) { return i + 1; }
unittest {
assert(foo(1) == 1); // should fail
}
You'll notice I don't have module declared at the top. I'm not sure if that matters for this specific question, but in reality I would have a module statement at the top.
How can I activate unit tests in a library with no main function?
You can use DMD's -main switch, or rdmd's --main switch, to add an empty main function to the set of compiled source files. This allows creating a unit test binary for your library.
If you use Dub, dub test will do something like the above automatically.

Is it possible to compile unittest without running them and explicitly run unittest for a specific module?

I often wrote my test code in the main function while developing an API but because D has integrated unittest I want to start using them.
My current work flow is the following, I have a script that watches for file changes in any .d files, if the scripts finds a modified file it will run dub build
The problem is that dub build doesn't seem to build the unittest
module foo
struct Bar{..}
unittest{
...
// some syntax error here
...
}
It only compiles the unittests if I explicitly run dub test. But I don't want to run and compile them at the same time.
The second problem is that I want to be able to run unittests for a single module for example
dub test module foo
Would this be possible?
You can program a custom test runner using the trait getUnittests.
getUnitTests
Takes one argument, a symbol of an aggregate (e.g. struct/class/module). The result is a tuple of all the unit test functions of that aggregate. The functions returned are like normal nested static functions, CTFE will work and UDA's will be accessible.
in your main() you should be able to write something that takes an arbitrary number of module:
void runModuleTests(Modules...)()
{
static if (Modules.length > 1)
runModuleTests!(Modules[1..$]);
else static if (Modules.length == 1)
foreach(test; __traits(getUnitTests, Modules[0])) test;
}
of course the switch -unittest must be passed to dmd

Haskell unit testing

I'm new to haskell and working on unit testing, however I find the ecosystem to be very confusing. I'm confused as to the relationship between HTF and HUnit.
In some examples I see you set up test cases, export them in an tests list, and then run in ghci with runTestsTT (like this HUnit example).
In other examples, you create a test runner tied into the cabal file that uses some preprocessor magic to find your tests like in this git example. Also it seems that HTF tests need to be prefixed with test_ or they aren't run? I had a hard time finding any documentation on that, I just noticed the pattern that everyone had.
Anyways, can someone help sort this out for me? What is considered the standard way of doing things in Haskell? What are the best practices? What is the easiest to set up and maintain?
Generally, any significant Haskell project is run with Cabal. This takes care of building, distribution, documentation (with the help of haddock), and testing.
The standard approach is to put your tests in the test directory and then set up a test suite in your .cabal file. This is detailed in the user manual. Here's what the test suite for one of my projects looks like
Test-Suite test-melody
type: exitcode-stdio-1.0
main-is: Main.hs
hs-source-dirs: test
build-depends: base >=4.6 && <4.7,
test-framework,
test-framework-hunit,
HUnit,
containers == 0.5.*
Then in the file test/Main.hs
import Test.HUnit
import Test.Framework
import Test.Framework.Providers.HUnit
import Data.Monoid
import Control.Monad
import Utils
pushTest :: Assertion
pushTest = [NumLit 1] ^? push (NumLit 1)
pushPopTest :: Assertion
pushPopTest = [] ^? (push (NumLit 0) >> void pop)
main :: IO ()
main = defaultMainWithOpts
[testCase "push" pushTest
,testCase "push-pop" pushPopTest]
mempty
Where Utils defines some nicer interfaces over HUnit.
For lighter-weight testing, I strongly recommend you use QuickCheck. It lets you write short properties and test them over a series of random inputs. For example:
-- Tests.hs
import Test.QuickCheck
prop_reverseReverse :: [Int] -> Bool
prop_reverseReverse xs = reverse (reverse xs) == xs
And then
$ ghci Tests.hs
> import Test.QuickCheck
> quickCheck prop_reverseReverse
.... Passed Tests (100/100)
I'm also newbie haskeller and I've found this introduction really helpful: "Getting started with HUnit". To summarize, I'll put here simple testing example of HUnit usage without .cabal project file:
Let's assume that we have module SafePrelude.hs:
module SafePrelude where
safeHead :: [a] -> Maybe a
safeHead [] = Nothing
safeHead (x:_) = Just x
we can put tests into TestSafePrelude.hs as follows:
module TestSafePrelude where
import Test.HUnit
import SafePrelude
testSafeHeadForEmptyList :: Test
testSafeHeadForEmptyList =
TestCase $ assertEqual "Should return Nothing for empty list"
Nothing (safeHead ([]::[Int]))
testSafeHeadForNonEmptyList :: Test
testSafeHeadForNonEmptyList =
TestCase $ assertEqual "Should return (Just head) for non empty list" (Just 1)
(safeHead ([1]::[Int]))
main :: IO Counts
main = runTestTT $ TestList [testSafeHeadForEmptyList, testSafeHeadForNonEmptyList]
Now it's easy to run tests using ghc:
runghc TestSafePrelude.hs
or hugs - in this case TestSafePrelude.hs has to be renamed to Main.hs (as far as I'm familiar with hugs) (don't forget to change module header too):
runhugs Main.hs
or any other haskell compiler ;-)
Of course there is more then that in HUnit, so I really recommend to read suggested tutorial and library User's Guide.
You've had answers to most of your questions, but you also asked about HTF, and how that works.
HTF is a framework that is designed for both unit testing -- it is backwards compatible with HUnit (it integrates and wraps it to provide extra functions) -- and property-based testing -- it integrates with quickcheck. It uses a preprocessor to locate tests so that you don't have to manually build a list. The preprocessor is added to your test source files using a pragma:
{-# OPTIONS_GHC -F -pgmF htfpp #-}
(alternatively, I guess you could add the same options to your ghc-options property in your cabal file, but I've never tried this so don't know if it is useful or not).
The preprocessor scans your module for top-level functions named test_xxxx or prop_xxxx and adds them to a list of tests for the module. You can either use this list directly by putting a main function in the module and running them (main = htfMain htf_thisModuleTests) or export them from the module, and have a main test program for multiple modules, which imports the modules with tests and runs all of them:
import {-# HTF_TESTS #-} ModuleA
import {-# HTF_TESTS #-} ModuleB
main :: IO ()
main = htfMain htf_importedTests
This program can be integrated with cabal using the technique described by #jozefg, or loaded into ghci and run interactively (although not on Windows - see https://github.com/skogsbaer/HTF/issues/60 for details).
Tasty is another alternative that provides a way of integrating different kinds of tests. It doesn't have a preprocessor like HTF, but has a module that performs similar functions using Template Haskell. Like HTF, it also relies on naming convention to identify your tests (in this case, case_xxxx rather than test_xxxx). In addition to HUnit and QuickCheck tests, it also has modules for handling a number of other test types.