jestjs / jest

Delightful JavaScript Testing.
https://jestjs.io
MIT License
44.31k stars 6.47k forks source link

Watch mode for only changed files (not affected files) or ignore some files when finding affected files. #8276

Closed AndrewSouthpaw closed 2 years ago

AndrewSouthpaw commented 5 years ago

🚀 Feature Proposal

  1. Allow watch mode to be configured to only run tests for files that were actually changes (instead of "affected" files), or
  2. Allow specifying files to be ignored when crawling the dependency tree for affected files.

Motivation

The watch mode looks for all specs affected by the change. Sounds great, but whenever I'm working on a file that is toward the root of the dependency tree (e.g. redux actions or reducers), it effectively re-runs everything.

For our mid-sized project, making a change in one reducer reruns 150 out of 206 test suites, rendering the watch functionality useless (it'll take ~30 seconds to complete); it takes longer for the watch to complete a run than to re-run all the tests (due to more workers).

While searching for a specific filename could work, it doesn't work as well when changing several files of different names or patterns. I tried this, and found myself spending an inordinate amount of time trying to specify filenames in the watch mode.

Example

Given a simple project like this one, assuming each file has a corresponding spec file:

// todos/reducer.js
export default reducer /* ... */

// lists/reducer.js
export default reducer /* ... */

// reducer.js
import todos from './todos/reducer'
import lists from './lists/reducer'

export const reducer = combineReducers({ todos, lists })

// components/todo.jsx
export class Todo extends React.Component { /* ... */ }

// app.jsx
import { createStore } from 'redux'
import { reducer} from './reducer'
import { render } from 'react-dom'

const store = createStore(reducer)
render(
  <Provider store={store} />
    {/* something that ends up using Todo component */}
  </Provider>
)

When running

jest --onlyActuallyChanged --watch or jest --ignoreFilesInDependencyTree="reducer.js" --watch

Making a change to todos/reducer.js will only trigger a rerun of todos/reducer_spec.js, instead of running tests for lists/reducer_spec.js, app_spec.jsx, and components/todo_spec.jsx.

Pitch

A very large part of the JS community use Redux, and presumably everyone is having to deal with this problem. This watch setting would not be as exhaustively correct, but would be a lot faster and probably an even better experience with more rapid feedback loops that developers seek. This goes for any developer working on modules that lie at the root of an app; watch mode just becomes not effective.

I want to emphasize that I ❤️Jest and think it's an excellent testing experience, but so far I've found --watch (which is commonly raved about and only demonstrated with small projects) to be very close to awesome but instead isn't quite useful in the real world.

scotthovestadt commented 5 years ago

Right now, there are a few features in watch mode to try and address the general problem:

Jest is correctly inferring that any of the dependency files may be broken by a change in the dependency. If you want to override that default behavior, you can use the filters in watch mode.

I'm not seeing how ignoreFilesInDependencyTree or onlyActuallyChanged would work generally, you'd also ignore the reducer's own test file. Jest doesn't make any assumptions about the way you have your tests setup. It doesn't "know" (and won't force you) to have a test file for each code file with a 1-1 mapping. That's what the dependency tree is used for.

Because the reducer is a top-level dependency here, implementing something like "only go X levels deep" won't help you.

I think the root "fix" for your core problem is a better IDE integration. You want to be able to easily configure the existing filters in a way that makes sense for what you're trying to test. You could do it today, but it requires going to the terminal, stopping the run, hitting a few keys... a "focus just this test file" hotkey or something similar might solve some of your pain. Work in this area is something I've been thinking about.

Let me know your thoughts. Pseudo-code for your suggestions if I misunderstood them is something I'd be interested to see.

AndrewSouthpaw commented 5 years ago

Thanks so much for the feedback! I had forgotten that Jest doesn't assume a 1-to-1 mapping.

I was working offering some additional thoughts, and then realized when working with a small sample project that maybe the watch functionality doesn't behave as I had thought or see in my project.

Given a tiny project like this one, similar to the pseudocode offered in the OP:

image

Am I correct in thinking that if I change todos/reducer.js it'll only run tests for app_spec.js, reducer_spec.js, and todos/reducer_spec.js? (I'm ignoring the __tests__ namespacing for simplicity of diagramming.)

Because right now I'm seeing something more like this:

image

where changing todos/reducer.js re-runs tests for essentially everything, even seemingly very unrelated files. Which makes me wonder how that might be happening...

jeysal commented 5 years ago

Am I correct in thinking that if I change todos/reducer.js it'll only run tests for app_spec.js, reducer_spec.js, and todos/reducer_spec.js?

Based on your dependency tree, that's how it should work.

Because right now I'm seeing something more like this:

If you can create a minimal repro from it, that'd be great!

AndrewSouthpaw commented 5 years ago

I'll keep digging and get back to you... thanks all for your patience and feedback.

github-actions[bot] commented 2 years ago

This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 14 days.

github-actions[bot] commented 2 years ago

This issue was closed because it has been stalled for 7 days with no activity. Please open a new issue if the issue is still relevant, linking to this one.

github-actions[bot] commented 2 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.