Testing behavior, not implementation
// don't [<Test>] let ``should hash user password with SHA1`` () = () // test body // do [<Test>] let ``should hash user password to make it unreadable`` () = ()
Unless hash algorithm is an explicit requirement, it should be considered an implementation detail.
You should never go down to a level of abstraction where your test expresses what the system should do. Instead, you should always test on what the feature expects of the system. The difference is that a test focusing on implementation will break on refactoring, whereas a test that focuses on behavior will not. Safe refactoring is one major part to why we're writing tests in the first place; so, we should really try to support this as much as we can.
This means that we don't explicitly test private methods, constructors, initializers, or patterns, unless they are backed up by a user story.