I can't help but feel like the authors of this tool (and ones like it) are fundamentally misunderstanding either the language, the purposes of testing, or maybe even static type systems in general.
This feels weird. I have a gut reaction to this, and it's conflicted. Perhaps the same feeling `redbad` has, perhaps not.
On the one hand, I feel like this is a million miles away from the Go I know and love. I've used Ruby, Python, C#, Java, C, Obj-C, JavaScript etc in the past. In terms of mental processes, the way I write go is closest the way I would write C or Java.
I write tests that do the same thing as this, that have pre and post conditions and assertions and explanations in comments. The whole point of static type systems, surely, is that you represent things (constraints, state, possible values, etc) in code rather than comments and rely on the language to enforce them rather than the next developer to read your comments, so the explosions happen at compile time rather than production. So, by that token, this kind of DSL seems like a step in the direction of static typing, rather than the other way round.
I've not looked at the source, but the line `Expect(scoreKeeper.Stats["Manning"]["Touchdowns"]).To(Equal(1))` might use all kinds of clever closure stuff but ultimately wouldn't compile if the right interfaces weren't satisfied. Unless there are `interface{}`s all over the place, which would be regrettable.
On the surface, this seems like a step toward Ruby with its endless DSLs which feels like the antithesis of static typing. That naturally feels a bit weird and a bit of a culture lurch. But perhaps the DSLs are closer to those of Scala than Ruby.
Both feelings I get are fuzzy and not particularly arguable, but I think peoples' relationships with languages are very personal and that's such a fundamental quality of the PL landscape that it's worth not discounting.
DSLs are not the antithesis of static typing. Beware of using the word strong when discussing type classification. That word is highly muddled and doesn't mean the same thing to everyone.
Haskell, for instance, is statically typed and does DSLs very very well. In fact, you use the type system as an augmentor of the DSL: it sets up the rules for how to embed the DSL in the code base itself. And it disallows a class of programs which would not work at all.
The right way to view types is that they allow a far richer description of what your code is doing because you can discriminate values on their types.
And before you lynch me: my professional work job is in Erlang which is a dynamically typed language.
You're right. Strong and static occur so often together (Go is both strong and static (mostly), for example) that I fell into the trap of glomming them both together. I've edited my post.
EDIT: And when I said 'the antithesis of static typing' I meant purely in the Ruby context, which is famous for its DSLs.
(context: i've been working mainly with python, and have almost no experience with go)
My initial reaction to the example was that it looked like something that could be easily unit-tested, without the added layer of BDD over the top. But that's probably just a symptom of the example appearing as something that would be simple to build and test.
E.g. in python i'd translate `Expect(scoreKeeper.Stats["Manning"]["Touchdowns"]).To(Equal(1))` to `assert scoreKeeper.Stats["Manning"]["Touchdowns"] == 1` which is essentially the same, but only uses one bit of machinery (assert) rather than three.
That said, the more ways to test things the merrier. I think if you are interested in testing larger chunks of functionality / user-facing bits of behaviour rather than invariants of the building blocks of your program, then perhaps BDD starts to look more appealing, so the two approaches seems complementary.
Having an expressive static type system is again complementary, as that prevents you from making many trivial errors, and you just have to test for the remaining ones that the type system cannot express. (i miss that in python)
after a little dig through the code, it looks like "EXPECT foo TO EQUAL barr" translates as
Unless I'm missing something, assert scoreKeeper.Stats["Manning"]["Touchdowns"] == 1 is not the same unless in python you have some magic reflection. The output you get from that is just pass/fail. The output you get from the matcher method is the expected and actual values in a much nicer error message.
you (& afandian) make a good point, and i believe that's roughly how py.test does it, by rewriting the code of test modules before running tests. which would be fair to call magic.
Like afandian, I'm a little fuzzy on the particulars of my gut reaction. But it's something along the lines of this: that BDD, or TDD, or test-oriented-development-practice-X didn't emerge from the ecosystems of dynamically-typed languages by accident. Those languages lack an entire class of verification that statically typed languages have by default, and which is actually important. So their practitioners abide tools, idioms, and practices to make up for that deficiency.
Those things aren't all bad, and _some_ of their lessons can be successfully "ported" to languages and ecosystems that don't suffer the same fundamental shortcomings as e.g. Ruby or Python. But when I see developers take e.g. the BDD ethos as axiomatic and just run with it, it makes me feel like they don't really understand what BDD is designed to address. Likewise with hyper-expressive testing DSLs, or the concept of "mocking" as it's normally used.
Forgive the loaded language, but bringing BDD et. al. to languages like Go feels, to me, like cargo-cult development.
So you're saying that static/strong typing == program future proofing? I guess what I'm trying to say is that even if your application or program is written in a statically typed language doesn't mean that someone can't screw something up when adding on new materials down the road, and having test suite backing you up is always a necessity.
Say you wanted to write a web application in Go, and you wanted to change your login system... Now it may be just me, but having a test suite to determine where you'd have breakages would DEFINITELY be handy in overhauling your login. Doesn't matter that it's statically typed.
I am absolutely not arguing that static/strong typing obviates the need for testing. Unit and integration tests absolutely have a place in statically-typed languages, and it is precisely as you describe: to ensure functional and business-level requirements.
Notice that I said "ensure", and not "describe" or "define". Because I think that's the disconnect. When you come from a dynamically-typed language background, I think you're more apt to believe your testing needs to describe/define your contracts, because you don't have a type system to leverage. But if you _do_ have a type system to leverage, the pathological context that justifies e.g. BDD is no longer valid, and tools like Ginkgo -- enabling "descriptive tests that can act as effective documentation" -- therefore don't make much sense. To me.
Maybe TDD emerged from dynamically typed languages because it is so much easier to write tests in a dynamically typed language?
When testing a statically typed language, you have to jump through a lot of hoops to create mock objects, shims and things like that to satisfy the compiler, especially with legacy code that wasn't written in an easy way to test.