> So I've fallen in love with dependency injection and Guice, is there
> anything in/for Go to facilitate dependency injection?
Just write the function/method/whatever such that it takes its
dependencies. There's no need for a fancy framework.
Dave.
> Don't you get the same functionality with "go test"?
That's completely orthogonal to DI. The former runs tests, and the
latter makes it easier to write testable code and its tests.
Dave.
So I've fallen in love with dependency injection and Guice, is there anything in/for Go to facilitate dependency injection?
So I've fallen in love with dependency injection and Guice, is there anything in/for Go to facilitate dependency injection?
> Do you mean that "go test" haven't got anything to do with DI? I don't know
> the term "dependency injection" well, but I do use "go test" for swapping in
> simplified "mock" implementations of dependent components when testing.
> Please explain what I am missing. It would seem to me that the "go
> test" supports what you want to do with DI.
DI is just a testing technique, or more generally a way to make code
independent of its dependencies. You can write tests with or without
DI, and you can use DI to help testing or for other reasons. There's
nothing for "go test" to support, any more than it needs to support
testing code that uses loops or writing table-driven tests.
Dave.
> So I've fallen in love with dependency injection and Guice<http://code.google.com/p/google-guice/>,
> is there anything in/for Go to facilitate dependency injection?
There are some examples in the standard library which rely on global
variables, notably the http package.
Wouldn't it be easier to build new tools to assist with testing rather than engineer our way around the lack of tools? Maybe doing so will drive the language adoption. :)Test Driven Development is a bit of a hassle in Go right now compared to Ruby/Python/Javascript/Java or any other language that has a real mocking library.
On Saturday, March 31, 2012 11:32:26 PM UTC-7, Albert Strasheim wrote:Hello
On Sunday, April 1, 2012 4:26:33 AM UTC+2, touca...@gmail.com wrote:So I've fallen in love with dependency injection and Guice, is there anything in/for Go to facilitate dependency injection?You can do all kinds of dependency injection "stuff" using Go's interfaces and embedding.I can really recommend looking at what can be achieved with a mix of embedding, other features of interfaces, picking good names for your structs and interfaces, splitting your code over packages, designing your New functions, understanding the issues of untagged struct literals and unexported fields and then putting it all together.You end up with great code and APIs that can be tested (with or without mocks) and reused in any way you can imagine.You probably don't need a Guice equivalent. At least not yet.CheersAlbert
--
Hmmm. Test Driven Development is all about writing the tests first...
But it gets tricky and complicated at the higher level where you have to integrate all of the modules together. Take the http handler for example, where it only accept HttpRespondeWriter and HttpRequest. How do you inject the dependencies in this case? Maybe you can wrap the http handler in a closure, but that is an unnecessary pain.
What you are saying is certainly possible at the component or module level where you have full control over the function interface.
But it gets tricky and complicated at the higher level where you have to integrate all of the modules together. Take the http handler for example, where it only accept HttpRespondeWriter and HttpRequest. How do you inject the dependencies in this case? Maybe you can wrap the http handler in a closure, but that is an unnecessary pain.
Can you give an example?
How do I stuff the database connection to the httpRequest interface?
- testing that fmt.Println(expr)
correctly prints expr?
You don't need to test it. It calls two functions that are already tested individually. Trying for 100% code coverage is a fool's errand.
On Friday, February 15, 2013 12:40:02 PM UTC-8, Nate Finch wrote:No, you're not testing PrintWithParens, but you're testing the meat underneath it.
So then how do I test PrintWithParens?--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
You don't need to test it. It calls two functions that are already tested individually. Trying for 100% code coverage is a fool's errand.
BTW, your code is dependent on the CPU performing correctly the machine code given, you should test it according to your methodology.
No, you should be writing code that makes its dependencies clear and controllable
You have brought over a lot of baggage from Ruby. That's
understandable, but baggage nonetheless. Go is not Ruby, just as Ruby
is not Java, and Java is not COBOL. What is natural in one language
may not be natural in another.
You care about dependencies of code, and that's good. So do we. The
difference is that Go makes those dependencies explicit, whereas your
Ruby experience is leading you to write code where the dependencies
are implicit or hidden, and thus testing involves monkey patching
those dependencies (or using a framework to do that for you).
--
No. You *do not* test the monkey patched version of anything. You test that the method under test *called* the monkey patched method with the *right arguments*. That is completely different than testing method B instead of method A, which is what you're talking about.On Fri, Feb 15, 2013 at 5:12 PM, Nate Finch <nate....@gmail.com> wrote:
On Feb 15, 2013 6:48 PM, "clay shentrup" <cl...@brokenladder.com> wrote:
>
> On Fri, Feb 15, 2013 at 3:21 PM, Nate Finch <nate....@gmail.com> wrote:
>>
>> You're assuming the interface parameter is public, but it doesn't have to be. You can make the public call not have the parameter, default it in that method and have a private implementation take an interface. The private implementation has the interface purely for testing purposes.
>
> But then I'd be testing the private interface, not the public one.Testing the private function is *exactly* the same as testing the monkey patched public function. *Exactly* the same, except one is visible and obvious, and one is hidden by magic.
--
clay shentrup | 415.295.CLAY
This is a bad programming practice, as it makes the code more flexible than it needs to be. If what I need is a function that writes a value to our Redis store, I *do not want/need* to give the caller the flexibility to specify the redis store. This relates to an important principle called YAGNI.
But this is not testing the same thing! There's a subtle difference. The first test actually proves that Foo() passes the right value to os.StdOut.Write. The second has no way to prove that Foo() passes os.StdOut to foo. And I just found out that Go doesn't let you compare equality of two functions, so you can't even prove that the right function is used in the default case. So this is a huge hole in testability for Go.
On Saturday, February 23, 2013 7:58:16 PM UTC-8, Jesse McNelis wrote:If I changed this line of code to instead write to a log file should I just update the tests to test for that function call instead?
Of course! That would be unit testing your code.
A unit test isn't going to explain why this function call would be important.
A unit test is going to verify that your code does the right thing. This complaint effectively argues against having unit tests.
It would also allow you to actually test your code's interaction with os.Stdout and whether it's properly handling it's errors, using it in a thread safe manner and that all the other code agrees on where to write output too.
You don't need an integration test for that. You just stub the call and ensure that it raises the error you want to ensure your code properly handles. E.g. in Ruby:
context "when there is an error"test_user = mock(User)User.stub(:find).and_raise("No such user")expect { UserUpdater.update(test_user) }.to raise_error "No such user"endIt's important to understand the differences between unit tests and integration tests.
Foo() in the above code is a wiring function and could be moved outside the unit under test
But then how do you test Foo?
On Saturday, February 23, 2013 9:16:23 PM UTC-8, Jesse McNelis wrote:On Sun, Feb 24, 2013 at 3:26 PM, <thebrok...@gmail.com> wrote:On Saturday, February 23, 2013 7:58:16 PM UTC-8, Jesse McNelis wrote:If I changed this line of code to instead write to a log file should I just update the tests to test for that function call instead?Of course! That would be unit testing your code.No, it's writing the same thing twice without any form of verification that it's correct. That's not testing, that's wasting time.
Let me repeat, unit tests and integration tests serves different purposes. Some key points are:1) Unit tests enable you to easily pinpoint what broke. As opposed to an integration test being more likely to tell me that something broke. E.g. if a controller spec fails and a model spec also fails (particularly a model that seems likely to have been related to that controller) then I can address the model spec first, and it will likely fix the controller test. The more high-level your view of an error is, the more challenging it can be to determine the underlying cause. If all I have are integration specs2) Unit tests make it feasible to do test permutations. E.g. if I have three methods and they each have 3 different conditional execution paths, then to full exercise those paths would require 27 contexts. Whereas if I just unit test each method, then I have 3+3+3=9 contexts. Much more tractable! Further, I'll get duplicate test setup if e.g. method X and method Y both call method Z, which has several permutations. I can instead test Z's permutations thoroughly, and then simply mock the calls X and Y make to Z. The key is to use this in conjunction with some high level integration tests that, while they don't test every permutation, ensure that these methods are wired up correctly.3) Unit tests can have dramatic performance benefits. E.g. if there's some intensive query/update job that must happen after a record is updated, I don't want to actually run the query job. I just want to assert that e.g. Resque.enqueue was called with UserReportUpdateJob. I have already tested elsewhere that this job works. I do not want to expend resources making this job run again for no reason.These are some very fundamental principles in test-driven development, and were some things I learned pretty early when pairing with engineers from Pivotal Labs—one of the thought leaders in TDD. These are important concepts that have dramatic consequences for the efficacy of your testing. You cannot just discard them because they don't ideologically sit right with you. If you use paid time to write 27 combinatorial integration tests when you could have written 9 unit tests and then a handful of integration tests to test the "gluing together" of those independently tested modules, then you're not being responsible with your employer's time. Or your own. You're going to be less successful as an engineer. Pragmatism is important.Moreover, your argument here is severely flawed. You said, "without any form of verification that it's correct". Well look—every test that isn't a browser-based total integration test is vulnerable to that criticism. If you ever stub out an API (which you certainly should) then you're doing unit testing. Unit testing and integration testing generally aren't black and white. Every integration test is effectively a unit test from the point of view of whatever calls the subsection of the code being tested in that integration test. If you provide an API for a client, then your entire high-level integration spec is just a unit spec, from the point of view of that client.Abstraction is crucial here.
Unit tests verify that a unit acts correctly, they aren't concerned with whether the unit interacts with the correct dependencies.
You're confused. Unit specs aren't concerned with whether the dependencies work. They take it for granted that the dependencies work. But they absolutely should test that the dependencies are interacted with correctly. If you think you can't write a unit test on anything that has dependencies, then you are going to be blatantly violating TellDon'tAsk/LawOfDemeter, and your code is going to be much less manageable as a result.You don't just throw decades of wisdom out the window because it offends your gut sensibilities.
The dependencies should be able to be swapped out for mocks or other implementations without making the unit test fail.
Only if that's part of the API of the method you're testing. If the job of the method is to take an implementation and pass a message to it, then the test is correct if it merely passes the implementing object to the function and asserts that it received the right message. But if the function under test is supposed to, say, write data to the "createFile" method, then you want to assert that it did that. What you do not want to do is implement the former when what you really need is the latter. You don't want more generality/flexibility than you need just because your language sucks for testability. The right solution is to fix your language.
Foo() in the above code is a wiring function and could be moved outside the unit under test
But then how do you test Foo?
since it's not concerned with the function of the unit but with what dependences it's interacting with.
Everything is a unit, depending on your perspective. You draw a box around any system, it's a unit with an API, from the perspective of the rest of the universe.
Since it's only concerned with the dependencies, it's only actually testable in an integration test.
This statement is just completely wrong. You clearly do not understand what constitutes an integration test vs. a unit test.Testing that Bob sends Alice a message is a unit test on Bob. Testing that Alice does something based on Bob's message is an integration test. (And from the point of view of the rest of the system, that whole thing is a unit test.) Having a dependency does not make your test an integration test. There are these things called stubbing and mocking that you should learn about if you want to write tests effectively.
In a unit test you can test whether the unit interacts correctly with some kind of mock of it's dependencies But since it's a mock and not the actual dependency it's only a guess at the interaction. Which is why integration tests exist.
No, it's not a "guess" in any sense. YOU the programmer KNOW what the external dependency is supposed to do. That WHY you can be safe stubbing/mocking it. Because you KNOW what it does and that the expected behavior is already tested. So here is a statement on a very elementary aspect of testing, and you got it exactly backwards.
You say "more flexible than it needs to be", but then immediately want
a way to make it more flexible for testing. You are treating testing
as some magical thing, when it is only code. This is a common problem
for testing fanatics: not realising that test code is still *code*. If
you have code A and it normally uses B, but for testing you want to
replace B with C, then A should just make that dependency injectable
in its interface, and then you won't be surprised when you discover
the A has some assumptions about B because they are less likely to
happen.
YAGNI is a fine principle, but here you obviously *do* need it: the
test wants the code under test to behave differently, so the code
needs to provide that flexibility.
Seriously: have you read through some of the Go standard library like
I suggested? Things fit together wonderfully, and it does not feel
verbose to do the minimal wiring. You can take compress/gzip.Reader,
give it a net.Conn, and all of a sudden you can decompress directly
from a network connection. All that from the trivial price of having
to pass an io.Reader to compress/gzip.NewReader.