<p>I'm in the middle of a large project and I decided to finally write tests. Very late, but it needs to be done for something like this.</p>
<p>My question is, do I need to refactor my code to be able to test it? Most of it is touching a Postgresql database. For example, here's a function I'd like to test..</p>
<p><a href="https://github.com/natdm/MobileBid/blob/master/database/event.go#L29-L62">https://github.com/natdm/MobileBid/blob/master/database/event.go#L29-L62</a></p>
<p>Did I write this so bad I can't test it? If so, how do I change it, as well as all the others?</p>
<hr/>**评论:**<br/><br/>dgryski: <pre><p>For a guide on writing testable code, see <a href="http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf" rel="nofollow">http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf</a></p>
<p>It's more geared towards Java / C++, but the concepts apply.</p>
<p>You might also be interested in some of the talks on <a href="https://gophervids.appspot.com/#tags=testing" rel="nofollow">https://gophervids.appspot.com/#tags=testing</a></p></pre>1Hzox73dcY: <pre><p>How about something like this:
<a href="https://play.golang.org/p/1Hzox73dcY" rel="nofollow">https://play.golang.org/p/1Hzox73dcY</a></p>
<p>In your "library" part of the application return errors so who ever calls it can decide how to handle it.</p>
<p>Avoid hard linking any components. Think about how to structure it so you can call as little code as possible (= easier testing).</p>
<p>Try to concentrate interaction with the "outside world" to as little places as possible and try to seperate them from the rest of the program. Try to work with a model of the world for as long as possible. Code that interacts with the outside is always a pain to test or mock.</p>
<p>Why do you use a channel instead of a return value?</p></pre>natdm: <pre><p>Thanks a lot for the example. I'll have to look at it. I may have a lot of refactoring to do.</p>
<p>I used a channel because the function that calls that calls multiple times on the DB, and it doesn't matter what gets done first, as long as they both get done..</p>
<p><a href="http://www.bbc.com/news/entertainment-arts-35856814" rel="nofollow">http://www.bbc.com/news/entertainment-arts-35856814</a></p></pre>sethammons: <pre><p>Some first impressions. </p>
<p>Run gofmt. I think you did not do this because of your import ordering. </p>
<p>Second thought, an advantage of TDD is you are forced to think of your API design and testing upfront, helping to prevent cases where dramatic refactoring is needed. </p>
<p>Third, it would appear you are making a new connection to the db with each call of <code>getDB()</code>; you don't need to do that as the sql package handles connection pooling and is safe to access concurrently. Instead of creating a new connection each time, just pass in the db. </p>
<p>As for testing, here are my initial thoughts. I tend to prefer passing an interface with matching methods into functions under test. You would have a test struct that matches the interface, and pass that in (and have its internals do what ever you need for your tests). If that is not easily achievable or your interfaces get unwieldy, you could look into dependency injection or mock objects. A sometimes unpopular opinion is to spin up a test database for the test run and remove it after. This may be the easiest approach, requiring the least amount of rework.</p>
<p>A couple of other thoughts as I glanced through the code. I see there is an endpoint that returns all users. At this point, you may not have many users. If you plan on ever having a large dataset, think about paginating results.</p>
<p>I see you are sending email through gmail. If you find deliverability to be an issue or you want to get some stats on your email, check out <a href="https://github.com/sendgrid/sendgrid-go" rel="nofollow">SendGrid's Go Library</a> (disclaimer, I work at SendGrid).</p>
<p>Cheers!</p></pre>Winsaucerer: <pre><blockquote>
<p>A sometimes unpopular opinion is to spin up a test database for the test run and remove it after</p>
</blockquote>
<p>One way to do this is using a combination of docker and drone (<a href="http://readme.drone.io/" rel="nofollow">http://readme.drone.io/</a>). You can have a test database docker container, and have drone automatically spin up the db for tests, run through everything, and then shut it all down.</p></pre>joushou: <pre><p>Unless you want a test that verifies the exact implementation (call A with string B, then call C with args... I see this occasionally, but find it rather useless), it's not very testable. If you have a test database, you can test that the entry appears, but this is an integration test, and a potentially heavy one.</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传