惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Securelist
C
CERT Recently Published Vulnerability Notes
Forbes - Security
Forbes - Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
L
LINUX DO - 最新话题
The Hacker News
The Hacker News
Google Online Security Blog
Google Online Security Blog
SecWiki News
SecWiki News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
The Last Watchdog
The Last Watchdog
S
Schneier on Security
T
Troy Hunt's Blog
N
News | PayPal Newsroom
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Schneier on Security
Schneier on Security
P
Privacy & Cybersecurity Law Blog
T
Tor Project blog
T
Threatpost
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
A
Arctic Wolf
S
Secure Thoughts
P
Proofpoint News Feed
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Security Latest
Security Latest
Scott Helme
Scott Helme
Security Archives - TechRepublic
Security Archives - TechRepublic
Latest news
Latest news
PCI Perspectives
PCI Perspectives
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
L
LINUX DO - 热门话题
P
Palo Alto Networks Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V2EX - 技术
V2EX - 技术
Google DeepMind News
Google DeepMind News
Project Zero
Project Zero
V
Vulnerabilities – Threatpost
T
Threat Research - Cisco Blogs
Webroot Blog
Webroot Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
N
News and Events Feed by Topic
TaoSecurity Blog
TaoSecurity Blog
大猫的无限游戏
大猫的无限游戏
T
Tenable Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
Visual Studio Blog
H
Hacker News: Front Page
Simon Willison's Weblog
Simon Willison's Weblog
AWS News Blog
AWS News Blog

Kent C. Dodds Blog

Implementing Hybrid Semantic + Lexical Search Simplifying Containers with Cloudflare Sandboxes Migrating to Workspaces and Nx Offloading FFmpeg with Cloudflare Building Semantic Search on my Content Helping YOU ask ME questions with AI How I used Cursor to Migrate Frameworks The Dow's Start on the Covenant Path 2025 in Review The next chapter: EpicAI.pro AI is taking your job How I increased my visibility Launching Epic Web 2023 in Review Stop Being a Junior RSC with Dan Abramov and Joe Savona Live Stream Fixing a Memory Leak in a Production Node.js App 2022 in Review My Car Accident I Migrated from a Postgres Cluster to Distributed SQLite with LiteFS I'm building EpicWeb.dev A review of my time at Remix Remix: The Yang to React's Yin How I help you build better websites Why I Love Remix The State Initializer Pattern How to React ⚛️ Get a catch block error message with TypeScript Building an awesome image loading experience How Remix makes CSS clashes predictable Introducing the new kentcdodds.com How I built a modern website in 2021 How to use React Context effectively Static vs Unit vs Integration vs E2E Testing for Frontend Apps The Testing Trophy and Testing Classifications Array reduce vs chaining vs for loop Don't Solve Problems, Eliminate Them Super Simple Start to Remix Super Simple Start to ESModules in Node.js JavaScript Pass By Value Function Parameters How to write a Constrained Identity Function (CIF) in TypeScript How to optimize your context value How to write a React Component in TypeScript TypeScript Function Syntaxes Listify a JavaScript Array Build vs Buy: Component Libraries edition Using fetch with TypeScript Wrapping React.useState with TypeScript Define function overload types with TypeScript 2020 in Review Business and Engineering alignment Hi, thanks for reaching out to me 👋 useEffect vs useLayoutEffect Super simple start to Firebase functions Super simple start to Netlify functions Super Simple Start to css variables Favor Progress Over Pride in Open Source Testing Implementation Details How getting into Open Source has been awesome for me useState lazy initialization and function updates Use ternaries rather than && in JSX Application State Management with React Use react-error-boundary to handle errors in React JavaScript to Know for React How I structure Express apps What open source project should I contribute to? When I follow TDD AHA Programming 💡 How I Record Educational Videos Should I write a test or fix a bug? Stop mocking fetch Intentional Career Building Improve test error messages of your abstractions Tracing user interactions with React Eliminate an entire category of bugs with a few simple tools Common mistakes with React Testing Library Super Simple Start to React Stop using client-side route redirects The State Reducer Pattern with React Hooks Function forms Replace axios with a simple custom fetch wrapper How to test custom React hooks React Production Performance Monitoring Should I useState or useReducer? Stop using isLoading booleans Make Your Test Fail Make your own DevTools An Argument for Automation Fix the "not wrapped in act(...)" warning Super Simple Start to ESModules in the Browser Implementing a simple state machine library in JavaScript 2010s Decade in Review Why users care about how you write code Why I avoid nesting closures Don't call a React function component Why your team needs TestingJavaScript.com Inversion of Control Understanding React's key prop How to Enable React Concurrent Mode Profile a React App for Performance
Common Testing Mistakes
2018-11-12 · via Kent C. Dodds Blog

Mistake Number 0

One of the biggest mistakes you could make would be missing out on my full Testing JS course. (see what I did there?)

Mistake Number 1: Testing Implementation Details

I harp on this a lot (read more). It's because it's a huge problem in testing and leads to tests that don't give nearly as much confidence as they could. Here's a very simple example of a test that's testing implementation details:

// counter.js
import * as React from 'react'

export class Counter extends React.Component {
	state = { count: 0 }
	increment = () => this.setState(({ count }) => ({ count: count + 1 }))
	render() {
		const { count } = this.state
		return <button onClick={this.increment}>{count}</button>
	}
}

// __tests__/counter.js
import * as React from 'react'
// (it's hard to test implementation details with React Testing Library,
//  so we'll use enzyme in this example 😅)
import { mount } from 'enzyme'
import { Counter } from '../counter'

test('the increment method increments count', () => {
	const wrapper = mount(<Counter />)
	// don't ever do this:
	expect(wrapper.instance().state.count).toBe(0)
	wrapper.instance().increment()
	expect(wrapper.instance().state.count).toBe(1)
})

So why is this testing implementation details? Why is it so bad to test implementation details? Here are two truths about tests that focus on implementation details like the test above:

  1. I can break the code and not the test (eg: I could make a typo in my button's onClick assignment)
  2. I can refactor the code and break the test (eg: I could rename increment to updateCount)

These kinds of tests are the worst to maintain because you're constantly updating them (due to point #2), and they don't even give you solid confidence (due to point #1).

In my course I'll show you the right way to write tests and avoid this common mistake.

Mistake Number 2: 100% code coverage

Trying to go for 100% code coverage for an application is a total mistake and I see this all the time. Interestingly I've normally seen this as a mandate from management, but wherever it's coming from it's coming out of a misunderstanding of what a code coverage report can and cannot tell you about the confidence you can have in your codebase.

What code coverage is telling you:

  • This code was run when your tests were run.

What code coverage is NOT telling you:

  • This code will work according to the business requirements.
  • This code works with all the other code in the application.
  • The application cannot get into a bad state

Another problem with code coverage reports is that every line of covered code adds just as much to the overall coverage report as any other line. What this means is that you can increase your code coverage just as much by adding tests to your "About us" page as you can by adding tests to your "Checkout" page. One of those things is more important than the other, and code coverage can't give you any insight into that for your codebase...

There's no one-size-fits-all solution for a good code coverage number to shoot for. Every application's needs are different. I concern myself less with the code coverage number and more with how confident I am that the important parts of my application are covered. I use the code coverage report to help me after I've already identified which parts of my application code are critical. It helps me to know if I'm missing some edge cases the code is covering but my tests are not.

I should note that for open source modules, going for 100% code coverage is totally appropriate because they're generally a lot easier to keep at 100% (because they're smaller and more isolated) and they're really important code due to the fact that they're shared in multiple projects.

I talked a bit about this in my livestream the other day, check it out!

Mistake Number 3: Repeat Testing

One of the biggest complaints people have about end-to-end (E2E) tests is how slow and brittle they are when compared to integration or unit tests. There's no way you'll ever get a single E2E test as fast or reliable as a single unit test. It's just never going to happen. That said a single E2E test will get you WAY more confidence than a single unit test. In fact, there are some corners of confidence that are impossible to get out of unit tests that E2E tests are great at, so it's definitely worth having them around!

But this doesn't mean that we can't make our E2E tests faster and more reliable than you've likely experienced in the past. Repeat testing is a common mistake that people make when writing E2E tests that contribute to the poor performance and reliability.

Tests should always work in isolation. So that means every test should be executed as a different user. So every test will need to register and login as a brand new user right? Right. So you need to have a few page objects for the registration and login pages because you'll be running through those pages in every test right? WRONG! That's the mistake!

Let's take a step back. Why are you writing tests? So you can ship your application with confidence that things wont break! Let's say you have 100 tests that need an authenticated user. How many times do you need to run through the "happy path" registration flow to be confident that flow works? 100 times or 1 time? I think it's safe to say that if it worked once, it should work every time. So those 99 extra runs don't give you any extra confidence. That's wasted effort.

So what do you do instead? I mean, we already established that your tests should work in isolation so you shouldn't be sharing a user between them. Here's what you do: make the same HTTP calls in your tests that your application makes when you register and log in a new user! Those requests will be MUCH faster than clicking and typing around the page and there's less of a chance for false negative failures. And as long as you keep one test around that actually does test the registration/login flow you haven't lost any confidence that this flow works.

Conclusion

Always remember the reason that you're testing is about confidence. If something your test is doing isn't bringing you more confidence, then consider whether you can stop doing it!

Good luck!