

How QA Engineers and Developers Can Work Better Together
Practical ways QA engineers and developers can improve communication, reduce unnecessary defect cycles and build better software together.
QA and development are sometimes treated like two separate stages of the same project. Developers build the feature, QA tests it, a bug is found, the ticket goes back, the developer fixes it and QA tests it again.
Technically, the process works. But it is also a very easy way to create unnecessary delays, misunderstandings and frustration between people who are supposed to be working towards the same result.
The best QA and development relationships I have seen are not based on throwing tickets over a wall.
They are based on shared context.
Why QA and development often become disconnected
A lot of the tension between developers and QA comes from the way work is organised.
In a traditional downstream process, development happens first and testing happens later. The developer spends days or weeks working on a feature and, once the code is considered ready, it is passed to QA.
The tester then starts looking at the behaviour and may immediately find problems with the logic, requirements or edge cases. At that point, the developer has often already mentally moved on.
The result is predictable. QA feels like the feature should have been thought through better, while the developer feels like QA is blocking progress.
The real problem may simply be that both sides started working with different assumptions.
Agile helps when QA is involved early
Agile does not automatically create good cooperation. Putting developers and QA engineers into the same sprint is not enough by itself.
But it does create the opportunity to work together earlier.
QA should understand the feature before the code is finished. That means being involved when the team discusses:
- Requirements
- Acceptance criteria
- User flows
- Edge cases
- Technical risks
- Dependencies
A tester who understands why the feature is being built can prepare better scenarios. A developer who hears QA questions early may notice missing logic before writing the full implementation.
Sometimes one simple question during planning can prevent several defect cycles later.
What should happen if the user repeats this action twice?
Can the system reach this state before the previous step is completed?
These are much cheaper questions to answer before release.
QA should not only appear when something is broken
If the only communication between QA and development is a bug report, the relationship will naturally become negative. QA becomes associated with problems and developers become associated with fixes.
That is not a healthy way to build software.
QA should also be involved when things are unclear. A quick discussion can often be better than creating a detailed defect report for behaviour that was never properly defined.
Imagine a tester finds that a cancelled transaction can still move into a processing state. Is it definitely a bug? Maybe. But before writing a long report, it may be worth asking:
Is this transition actually allowed?
The answer could immediately reveal a missing business rule.
The goal is not to create as many bug tickets as possible. The goal is to understand product behaviour and reduce risk.
Clear acceptance criteria make everybody's job easier
Poor requirements create unnecessary conflict.
If a ticket only says “User can edit the offer”, that is not enough. What exactly can the user edit? Can they edit it after somebody has accepted it? Can the amount be reduced below an existing contract value? What happens to active users viewing the old data? Does the update happen immediately?
Good acceptance criteria give developers and QA the same starting point. They do not need to describe every possible test case, but they should define the important business behaviour.
For example:
- The user can edit the offer while no active contract exists.
- Updating the amount immediately changes the public offer.
- Existing contracts keep the original terms.
- Invalid values return a clear validation error.
Now both sides understand the intended result.
QA can build meaningful tests and developers can implement against clearer expectations.
QA should understand how the feature is built
A QA engineer does not need to become a developer, but understanding the basic technical structure of a feature makes cooperation much easier.
Imagine the tester knows that a user action triggers:
- A frontend request
- Backend validation
- A database update
- An external API call
- A notification
That information immediately creates better questions. What happens if the external API fails after the database update? Can the user repeat the request? Is the operation idempotent? Can the frontend display an old state while the backend has already changed?
Technical context helps QA investigate deeper and makes bug reports more useful because the tester can provide better evidence.
Instead of saying “Payment is broken”, the report may explain that the frontend shows the payment as failed while the API returns a successful transaction state, and that refreshing the page shows the payment as completed.
That gives the developer a much stronger starting point.
Developers should understand how QA thinks
This works in the other direction too. Developers benefit from understanding why QA tests strange scenarios.
A tester may:
- Click the same button several times
- Send an invalid value
- Interrupt the flow halfway through
- Switch accounts
- Refresh at an unusual moment
- Repeat an old request
From a normal user-flow perspective, some of these actions may look unrealistic. But testers are often looking for state problems, race conditions and assumptions inside the system.
A developer who understands this is less likely to ask “Why would a user ever do that?”
The better question is:
What happens if they do?
Software rarely breaks only because users follow the intended flow.
TDD is primarily a development practice, but the thinking behind it can also improve cooperation between developers and QA.
The important question is discussed early:
How will we know this feature works?
That conversation can involve both technical tests and product behaviour. A developer may focus on unit-level conditions, while QA may identify missing user scenarios or state transitions.
The approaches are different, but the goal is shared.
It is also worth saying that TDD is not the answer for every team or every feature. The useful part is the early discussion around expected behaviour.
Prioritise defects based on risk
Not every defect is equally important. This sounds obvious, but QA and development teams still lose time arguing over relatively small issues while larger risks are waiting.
A typo in a rarely opened settings page is not the same as an incorrect payment state.
QA should understand the product well enough to explain why a defect matters.
Severity should consider:
- Affected user flow
- Number of users impacted
- Financial or data risk
- Possibility of recovery
- Frequency
- Release impact
A useful defect report does not simply say “This is critical.” It explains the risk.
For example, if the user can submit the payment request twice before the first response is completed, the report should explain that this may create duplicate transactions and should be treated as a release blocker.
Clear risk makes prioritisation easier and helps developers focus on the problems with the highest impact.
Avoid turning bug reports into arguments
A bug report should describe behaviour. It should not describe blame.
Compare “Developer forgot to validate the amount” with “The API accepts a negative amount and creates the transaction successfully.”
The second version is objective and gives the team something concrete to investigate.
The same applies when a developer disagrees with a defect. The discussion should return to:
- Current behaviour
- Expected behaviour
- Requirement
- User impact
Sometimes QA is wrong. Sometimes development misunderstood the requirement. Sometimes the requirement itself is incomplete.
None of those situations improve when the conversation becomes personal.
Use the same evidence
One of the easiest ways to improve cooperation is to give everyone access to the same information.
Useful evidence may include:
- Request and response data
- Logs
- Screenshots
- Video
- Browser console output
- Database state
- Timestamps
- Environment details
Imagine a bug only happens intermittently. Saying “It sometimes fails” does not give the developer much to work with.
Instead, collect what you can. A better report might explain that the issue reproduced 3 times from 10 attempts on staging, include the request timestamp, mention that the API returned `409`, and explain that the frontend remained in a loading state until refresh.
The issue may still be difficult to reproduce, but the investigation now has a starting point.
Small conversations are often faster than long ticket chains
Not every question needs five Jira comments.
Sometimes the best solution is a short message:
Can we quickly check this flow together? I may be misunderstanding the intended state.
Ten minutes of screen sharing can save hours of asynchronous discussion.
This is especially useful when:
- Reproduction is difficult
- The feature has several states
- Requirements are unclear
- The issue may involve several services
Documentation is important, but communication should not become slower just because the team has a ticketing system.
Remote teams can cooperate just as well
Distance is not automatically the problem. Poor communication is.
Remote teams have access to chat, video calls, screen sharing, issue trackers, shared documentation, test management tools and recorded discussions.
In some cases, remote work can actually make decisions easier to review because more communication is written down.
But remote cooperation needs to be intentional. The team should know:
- Where questions are asked
- Where decisions are documented
- When a quick call is better
- Who owns the final product decision
A remote QA engineer who disappears for two days and returns with 40 defect tickets is difficult to work with. A developer who changes important behaviour without updating the ticket creates the same problem.
Location is not the deciding factor. Visibility is.
Quality is not only QA's responsibility
One of the worst ideas a software team can have is “QA is responsible for quality.”
QA is responsible for testing, investigation, risk communication and many other quality-related activities, but QA cannot create quality alone.
Developers make technical decisions. Product defines behaviour. Design affects usability. Infrastructure affects reliability. Management affects deadlines and scope.
Everybody influences the final result.
QA can identify that a release is risky, but if the organisation chooses to release anyway, the tester did not suddenly become responsible for the defects that follow.
A better approach is shared ownership.
Developers should care about testability. QA should understand technical constraints. Product should clarify business rules. The team should make release decisions based on the same information.
The best QA and developer relationships are practical
Developers and QA engineers do not need to agree on everything. In fact, disagreement can be useful.
QA may question a flow that development considers technically correct. A developer may explain why a test scenario is impossible based on the architecture. Both sides learn something.
The problem starts when QA is treated as the final gate at the end of development, or when developers see testing as somebody else's problem.
Good cooperation starts earlier. Clear requirements help. Technical context helps. Better bug reports help. Quick conversations help.
Most importantly, both sides need to remember that coding and testing are not the final goal.
The product is.
And users do not care which team caused the problem. They only see that the software does not work.
Need practical QA support?
Laidoner Solutions helps software teams with manual QA, API testing, localization review, release checks and clear defect reporting.
Contact Us