Skip to content
Notifications
Clear all

Am I the only one who turns off Tabnine for test files?

44 Posts
40 Users
0 Reactions
175 Views
(@georgek)
Reputable Member
Joined: 2 months ago
Posts: 217
 

The quantifiable latency you measured is fascinating and mirrors our internal tracking for code review cycles. We found the "semantically hostile" suggestions, especially in failure mode testing, created a kind of mental debt that later showed up as more superficial review comments. Reviewers, having been conditioned by the tool's patterns in production code, would sometimes apply that same expectation for generic assertions when glancing at tests.

Your question about copy-pasted assertions is perceptive. Even with the tool disabled, we observed a subtle increase in pattern-matching from nearby tests. It's not direct copying from Tabnine, but I suspect the tool's influence in our main codebase creates a stylistic baseline that seeps into test writing by osmosis. The team starts to expect a certain verbosity or structure, which then gets replicated manually in test files. It's less about the tool's direct output and more about the coding style it nudges everyone towards.

So the cost isn't just the 500ms dismissal delay, it's the gradual homogenization of intent.



   
ReplyQuote
(@chrism)
Reputable Member
Joined: 3 months ago
Posts: 326
 

You're spot on about the compliance angle making this extra frustrating. We went the on-prem route for Tabnine too, and hitting that exact `assertTh` -> `assertThat().isNotNull()` pattern in our API contract tests felt like a betrayal, ha. Like, we jumped through hoops to get this secure tool inside our walls, only to have it fight us on the one thing we need to be precise about.

Your point on cognitive interruption is key. For me, it's less about the dismissal speed and more about the mental shift. That half-second to process the suggestion pulls me out of "what am I trying to break here?" and into "what does this tool think I'm doing?" It's a complete context break.

We ended up using the path-based disabling as a stopgap, but it feels like a workaround for a tool that doesn't understand intent. Makes me wonder if the real fix is a model specifically tuned for test scaffolding, not logic.


K8s enthusiast


   
ReplyQuote
(@danielj)
Reputable Member
Joined: 3 months ago
Posts: 254
 

Totally with you on this. That `assertTh` -> `isNotNull()` example is painfully accurate. It's actively working against good test design by pushing you toward the most statistically common, but often least valuable, line of code.

The on-prem compliance angle makes it sting more, doesn't it? We justified the spend and setup for security, only to have to neuter the tool in the one place where creative thinking and precision matter most. Feels like a feature gap they should address - maybe a "test mode" that only suggests scaffolding (like test method names or setup blocks) and leaves the logic entirely to the developer.

I've found disabling it also removes a weird social pressure - if a junior dev sees the tool constantly suggesting trivial assertions, they might think that's what we value. Turning it off sends a clear message: think for yourself here.


spreadsheet ninja


   
ReplyQuote
(@datadog)
Reputable Member
Joined: 3 months ago
Posts: 365
 

"Test mode" is the right idea, but it's still a filter on a model trained for the wrong goal. It suggests structure because that's all it can parse from tests, not because it understands the intent.

You're right about the social pressure. Our juniors started cargo-culting those `isNotNull()` assertions into performance test baselines. Took weeks to unwind the habit. The tool's suggestion became the team's standard.

We solved it by blocking Tabnine on any file matching `*Test*.java`. The ROI improved immediately.


Metrics don't lie.


   
ReplyQuote
(@carolinem)
Reputable Member
Joined: 2 months ago
Posts: 355
 

Your observation about the pursuit of the *correct* assertion versus the *common* one is precisely aligned with the literature on test-driven development and cognitive load. The seminal paper "The Psychology of Software Testing" by Kaner et al. discusses how effective testing requires a mindset oriented towards "breaking" and exploring boundaries, which is fundamentally at odds with tools optimized for pattern completion.

You're experiencing a concrete manifestation of the "streetlight effect" in AI-assisted coding. The model is biased towards the well-lit, high-frequency patterns in its training data, which in test files often represent the most superficial verification points. This doesn't just cause a dismissal interrupt; it actively reinforces a bias towards confirmatory rather than adversarial testing.

Our team's solution was similar, but we extended the path-based exclusion to also cover integration test patterns (`*IT.java`, `*Spec.scala`). We found the problem was even more pronounced in integration tests, where the tool would suggest trivial setup/teardown boilerplate that obscured the actual system interaction under test.


Nullius in verba


   
ReplyQuote
(@data_diver_43)
Reputable Member
Joined: 4 months ago
Posts: 292
 

That's a really solid example with the assertThrows vs isNotNull. I can relate, but maybe from the opposite direction? I'm still new enough that I sometimes default to those common assertions without thinking it through.

So when Tabnine pops that generic suggestion, I actually have to stop and ask myself "wait, is that really what I should be testing here?" It forces a second of reflection that I might have skipped otherwise.

But you're right, once you know what you're doing, that interruption is just noise. Makes me wonder if there's a sweet spot for juniors where it's briefly helpful before it becomes a hindrance.



   
ReplyQuote
(@gracehopper2)
Reputable Member
Joined: 3 months ago
Posts: 388
 

That's a really interesting perspective, and I think you're onto something about a "sweet spot." For a junior developer, that moment of reflection forced by a generic suggestion can be a valuable learning prompt. It asks you to stop and validate your own thinking.

The danger, as others have hinted, is when that pattern becomes the default. If you start to see those generic suggestions as *the* correct answer, rather than a prompt to question, you've missed the learning opportunity. The tool can't distinguish between teaching you to think and teaching you what to type.

I've seen teams try to capture that sweet spot by using the tool in test files only during paired programming sessions, so there's an immediate human there to discuss *why* the suggestion is wrong. It turns the interruption into a conversation.


ship early, test often


   
ReplyQuote
(@integration_tester_mike)
Reputable Member
Joined: 5 months ago
Posts: 196
 

You've perfectly articulated the central conflict. The tool is optimized for throughput on repetitive, high-frequency patterns, which is the exact opposite of what you need when designing a test. In integration work, I see this manifest in API contract tests where Tabnine will aggressively suggest verifying a 200 OK status code, completely missing the point that the test's value is in verifying the *structure* of the response body or the idempotency behavior on a 429.

Our team's stopgap was similar to yours, but we extended the path-based disable logic to also cover any file with a naming pattern for mock data or contract schemas. It's not just about the test runner, it's about any file where the cognitive goal shifts from "implement common pattern" to "define specific, intentional behavior."


- Mike


   
ReplyQuote
(@finops_auditor_ray)
Honorable Member
Joined: 6 months ago
Posts: 467
 

Team defaults sound good on paper, but who enforces them and at what cost? You're just trading one cognitive tax (dismissing suggestions) for another (managing and verifying compliance with the rule).

Show me the PR review velocity metrics before and after that policy. If it's just anecdotal "feels better," you haven't solved drift, you've just moved it to a configuration file. Someone still has to catch the junior dev who didn't get the memo or whose IDE settings didn't sync.

The real cost is in the exceptions. What about those hybrid files that have both utility functions and test fixtures? Now you're arguing about path patterns instead of code.


show me the bill


   
ReplyQuote
(@ethanb8)
Reputable Member
Joined: 3 months ago
Posts: 417
 

That specific assertion example hits home. I've seen the same thing happen when typing `verify(` in a mock-heavy test, where it desperately wants to complete to `verify(mock).someDefaultMethod()` instead of letting me specify the exact interaction I'm checking for.

The cognitive interruption you describe is real, but I think it's worse than just a speed bump. It can actually steer the design of the test itself. If you're fighting the tool for three lines in a row, you might unconsciously simplify what you're trying to verify just to stop the conflict. The tool wins, and the test gets worse.

Your team's path-based disable sounds like the right pragmatic fix. Have you found it holds up, or do you get friction from devs who forget and then get annoyed when it's off for a legitimate utility method inside a test source tree?


Keep it civil, keep it real


   
ReplyQuote
(@infra_switcher)
Reputable Member
Joined: 4 months ago
Posts: 320
 

> It can actually steer the design of the test itself.

That's the real cost, and it's insidious. You start writing tests for the autocomplete, not for the system. The path-based disable is just a bandage on a workflow problem.

We did get friction. It came from the hybrid files, exactly as you suspect. Someone writes a `PaymentTestUtils` class in a test source root, loses autocomplete for a complex builder pattern, and we spend 30 minutes debating whether to add an exception to the glob pattern. The rule becomes a distraction in itself.

The only thing that held up was moving the decision to the IDE profile level and making it a personal toggle. If a developer feels the tool helps them scaffold a `@BeforeEach` block, they can leave it on. When they get tired of fighting `verify(mock).somethingGeneric`, they turn it off. Enforcing it as team policy creates more problems than it solves.


Been there, migrated that


   
ReplyQuote
(@amandaf)
Reputable Member
Joined: 3 months ago
Posts: 455
 

No, you're not the only one, and the specific example you gave is the exact reason our team implemented the same rule. It's not just about a nuisance. That automatic completion to a trivial `isNotNull()` actively undermines test design by pushing the lowest-common-denominator check.

Where we diverged is in enforcement. Making it a team-wide mandate created more friction than it solved, as developers working on complex test utilities in those directories lost valid assistance. We had to walk it back to a strong recommendation with individual control. The principle is right, but rigid policy often breaks on the hybrid file cases.


β€”AF


   
ReplyQuote
(@gracyj)
Reputable Member
Joined: 3 months ago
Posts: 282
 

Totally feel that friction on team mandates. We tried the same thing and hit the same wall with those hybrid utility files. 😅

Your point about it becoming a "strong recommendation" is exactly where we landed too. It's more about guiding the *why* than policing the *how*. Sometimes a quick "hey, have you considered turning it off for tests?" during a pairing session sticks better than any rule in the config.

That individual control seems to be the only thing that scales without the drama.


Happy customers, happy life.


   
ReplyQuote
(@deborahw)
Reputable Member
Joined: 3 months ago
Posts: 358
 

Individual control does scale better, until someone submits an expense report for their "productivity suite" that promises to solve this exact problem. Suddenly there's a business case for a paid team license with centralized policy management.

So you trade a local config debate for a vendor contract, and the hybrid file problem just becomes a support ticket.


β€”DW


   
ReplyQuote
Page 3 / 3