今日推荐开源项目:《YTB DevYouTubeList》
今日推荐英文原文:《Stop Testing Code You’ve Already Written》
今日推荐开源项目:《YTB DevYouTubeList》传送门:GitHub链接
推荐理由:YTB 上你能看到几乎所有想看的玩意,总会有人去做它们的。这个项目收集了 YouTube 上与软件开发有关的频道,包括开发教程或者是编程直播之类的,下次可以考虑拿这个来打发时间下饭之类的(我可没试过拿这些下饭),当然了大部分的资源都是英语,至于你要问有没有非英语……只有俄语可以吗?
今日推荐英文原文:《Stop Testing Code You’ve Already Written》作者:Jamie Morris
原文链接:https://medium.com/@maloric/stop-testing-code-youve-already-written-750773b9bb5b
推荐理由:测试也是一步一个脚印来的,这篇文章介绍了测试驱动开发的优点
Stop Testing Code You’ve Already Written
Test One Step at a Time, Not One Mountain at a Time
It’s that time of year where we start to make promises that we’ll probably just forget by February. New Years Resolutions are usually well meaning but we are usually trying to solve the same old problems in ways we’ve tried before. Eat healthy. Go to the gym more. Learn a new language. Write more unit tests.Every time I talk to a team that’s struggling and ask them what they’ll do different next time, I always get the same answer: we’ll write more tests. Sometimes there are other answers thrown in there, but testing is the thing we all think we should be doing better.
The same teams have made the same resolution time and time again, so I wonder why it is that teams like this aren’t writing enough tests. “Enough tests” may be a poor choice of words — the quality of your tests is just as important as the quantity. But either way: based on my own anecdotal findings, most of us think we should be writing more / better tests.
So why don’t we? When I think about it logically, there is an obvious conclusion (obvious to someone who is fanatical about TDD). It’s hard to write tests after the fact.
You see, test driven development forces you to write code in small steps that are easily testable. I might write one test, then write another few lines, followed by another test, followed by another few lines.
But most teams who write their tests after they write their features don’t work with this incremental approach. You might write 200 lines of code before you start testing it. That leaves you with a working feature, little incentive to test it, and a lot of refactoring to do before you finish.
Why refactoring? Well, those 200 lines may not be easy to test. In order to make them testable, you’ll need to refactor a little. Refactoring can easily break your code, but at least you have a safety net of tests to… oh wait. See the problem?
So write your tests first. Not only will it give you a safety net from the start, but it will also mean one less refactor. Or more accurately, it will mean that refactor will be broken down into smaller chunks that are easier to manage.
What is TDD and Why Should You Care About It?
Test Driven Development is the act of writing your tests before you write the code you are testing. Want to write a feature that allows you to add a product to your basket? Start by writing a tests that checks if the feature works. The test will fail, because the feature hasn’t been written yet. Then you can write the feature to make the test pass. Simple, right?How Do I Test Something I Haven’t Written Yet?
If you want to test 200 lines of code you haven’t written yet, you’ll have a tough time doing it. It’s hard enough to think about the next 200 lines when you are writing them, never mind when you are trying to figure out how to test them. The idea isn’t to write a whole feature’s worth of tests before you get started on the implementation. That would require incredible foresight to know exactly how you will implement the feature, without the benefit of any kind of feedback.Instead, you test just enough to cause a test failure. This keeps you focused on the problem directly in front of you rather than the final destination. As always, I find examples help in this situation:
Let’s say you are writing a basket on an eCommerce website. At present adding a product doesn’t check the stock levels before adding an item to the basket. You’ve been asked to make sure products can only be added to the basket when they are in stock.
There are a whole bunch of tests you might think of at the outset. Here are some of the ones I thought of:
- Given that Product A is in stock (quantity > 0)
When I add Product A to my basket
Then there should be 1 x Product A in my basket - Given that Product A is in stock (quantity = 0)
When I add Product A to my basket
Then there should be an error telling me the item is not in stock - Given that Product A is in stock (quantity = 1)
When I add 2 x Product A to my basket
Then there should be an error telling me there is not sufficient stock
Your first test might only look like this:
it('should add an item to the basket when it is in stock', () => {
let mockStockService = {};
let basket = new Basket(mockStockService);
});
This isn’t much of a test — there aren’t even any assertions yet! But when considering how to check stock levels, I decided I would need to inject a service to do so. As soon as I try to instantiate the Basket class with this service, I get an error because the constructor does not expect any arguments. This is a failing test, even if it is only caused by a compilation failure rather than an assertion.I don’t know exactly what methods will be on the service yet, but I can now update the Basket class to accept a StockService in its constructor. With that done, the test should “pass” (i.e. compile), at which point I can move onto my first assertion:
it('should add an item to the basket when it is in stock', () => {
let mockStockService = {
getStockLevel: jasmine.createSpy()
};
let basket = new Basket(mockStockService);
basket.add(new Product(123));
expect(mockStockService.getStockLevel).toHaveBeenCalledWith(123);
});
Again, I have wrote the minimum amount to make a test fail. I decided that I need a method called getStockLevel so I implemented a spy, but not a return value. I just want to get to the next assertion.This doesn’t mean you’re only thinking about one problem at a time, but simply that the ones in sharpest focus are the ones closest to you right now. Don’t focus on a problem you don’t have to solve yet, because you will take brain power away from the ones you do. And by the time you have to solve that faraway problem, it may look a whole lot different.
This is one thing that I think people forget to explain about Test Driven Development. It’s not just about writing better tests, but it naturally breaks big problems down into bitesize pieces. As a result, testing can often feel much less daunting than it would if you had 200 lines of code to test. You’re generally just trying to find the minimum amount of test that will cause the test run to fail, followed by the minimum amount of code to make it pass.
Then you refactor, if needed. This time you have a safety net in the form of the test you just wrote. This process is often called Red, Green, Refactor.
- Red is when you have a failing test.
- Green is when the test is passing.
- Refactor is when you look at how you made the test pass and decide there is a better way. Rather than saying “we’ll fix that later” you make an effort to fix it now, while it’s fresh in your mind.
So stop writing tests for code you’ve written and start writing tests for code you haven’t written yet.
下载开源日报APP:https://openingsource.org/2579/
加入我们:https://openingsource.org/about/join/
关注我们:https://openingsource.org/about/love/