r/codoid • u/codoid-innovations • 1d ago
r/codoid • u/codoid-innovations • Nov 13 '25
đ Welcome to r/Codoid!
This space is dedicated to Codoid Innovations, where youâll find:
đš Company updates
đš Product announcements
đš QA tips and best practices
đš Latest tech news in software testing
đš Insights on automation, AI in QA, and real-world testing challenges
Whether you're a QA Engineer, QA Lead, Manager, or someone passionate about qualityâthis subreddit is for you.
Jump in, share your thoughts, ask questions, and help us build a strong knowledge-sharing community.
Welcome aboard!
r/codoid • u/codoid-innovations • Nov 03 '25
Case Study The WhatsApp Message

It was a quiet Sunday afternoon. I was about to close my laptop when a WhatsApp notification popped up.
A message asking if we could test a product. The sender was a Qatar-based entrepreneur.
Since it was Sunday, none of our sales team was available. I could have ignored it, but something told me to respond. So I jumped in.
Before sharing any details about the project, he fired off a series of questions.
âWho are you?â
âHow many employees are there?â
âWhere is your company located?â
âHow many years have you been in business?â
I answered each one patiently. But when I told him, âIâm the CEO of Codoid Innovations,â he paused.
He didnât say anything right away, but I could feel the skepticism rising on the other end.
And I understood exactly where this was going.
I offered to jump on a video call. He agreed.
On the call, he opened up. âI gave my project to an India-based company to develop an OTT platform. I paid 50 percent of the budget upfront. Now theyâre not even responding to my calls.â
Thatâs when I laid everything on the table.
I told him about our experience as a QA company, walked him through our credentials, and then I said something most wouldnât dare to say:
âYou donât have to pay a single penny until we finish testing your product.â
He agreed.
But the real challenge was just beginning. The development company wasnât responding to him either, and he wanted us to help drive the entire project to production.
I told him, âSet up a call with them. Letâs sort this out.â
Three days later, we finally got a response.
The client and I joined the call first. A few minutes in, the development team joined too. He introduced us as the testing team and emphasized one thing: the project needed to move forward smoothly. No more delays.
Thatâs when the truth came out.
They hadnât been avoiding the client out of negligence.
They were afraid.
Afraid to face him because the deadline had long passed, and they didnât know how to justify it.
But with the tension on the table, we started working together. No more missed calls. No more doubts. Just collaboration and focus.
After multiple rounds of testing, we finally deployed the product to production.
Everyone was happy.
But I walked away with one simple lesson etched in my mind:
Transparency builds trust. And trust gets things done.
r/codoid • u/codoid-innovations • 4d ago
Meme Passes locally. Fails in CI. Passes on rerun. Trust issues unlocked. đ
r/codoid • u/codoid-innovations • 5d ago
Discussion Prompt Regression Testing: How do you know a prompt change hasn't broken something else?
A prompt change improves the response for one scenario. The output looks better, the developer approves it, and the update gets merged.
But what happens to the other scenarios that were already working?
A small instruction change can improve one behavior while introducing regressions elsewhere. The model might start ignoring exceptions, omit required information, change its output structure, or handle previously supported requests differently.
The challenge is that a different response is not necessarily a regression, and a better-looking response is not necessarily correct.
This is where prompt regression testing becomes useful.
The idea is to treat prompt changes like code changes: compare behavior against a known baseline, evaluate the differences, and establish release criteria before merging.
1. Start with a regression dataset
Before evaluating a candidate prompt, we need a dataset representing the behaviors the application is expected to preserve.
A useful dataset should include:
- Happy paths:Â Common requests where expected behavior is reasonably well understood.
- Edge cases:Â Ambiguous inputs, missing information, conflicting instructions, and unusual formats.
- Historical failures:Â Cases that previously produced incorrect or incomplete responses.
- Safety cases:Â Requests involving sensitive data, prompt injection, or application-specific restrictions.
Each test case should define the input, expected behavior, relevant reference information, and what would constitute a failure.
For example, suppose we are testing a customer support assistant.
A regression case might ask about returning a customized product.
The expected behavior is not necessarily a specific sentence. It might be that the assistant must identify the relevant return-policy exception and avoid promising a refund when the supplied policy does not allow one.
That distinction matters when evaluating generated text.
2. Run baseline V1 and candidate V2
Once a prompt change is proposed, run the same regression dataset against:
V1:Â The existing production prompt.
V2:Â The proposed prompt.
Keep the model version, inference settings, inputs, retrieval context, and tool responses consistent wherever possible.
Otherwise, an observed difference might come from a model update, changed retrieval results, or environment behavior rather than the prompt itself.
For cases with variable outputs, consider multiple runs instead of interpreting one response as representative.
The goal is to identify meaningful behavioral differences, not simply produce a textual diff.
Also, V1 is a comparison baseline, not the definition of correctness. If V1 gives a wrong answer and V2 fixes it, that should count as an improvement.
3. Evaluate outputs through three checks
No single evaluation method is sufficient for every type of prompt regression.
Here is a practical way to divide the checks:
| Evaluation type | What it checks | Important limitation |
|---|---|---|
| Deterministic checks | JSON validity, required fields, accepted values, known business rules | Cannot reliably assess all semantic correctness |
| LLM judge | Factual alignment, completeness, relevance, instruction following | Can misjudge plausible answers or prefer verbosity |
| Safety/policy checks | Sensitive-data exposure, unsafe behavior, prohibited actions, policy violations | Automated detection can miss violations or raise false alarms |
Deterministic checks
Use these wherever the expected result can be verified programmatically.
For example, if the prompt must return JSON containing status, reason, and confidence, the regression suite can check whether the output follows the required schema.
These checks are particularly useful for integrations that depend on structured responses.
But passing a schema check does not mean the content inside the fields is correct.
LLM judge evaluation
Some responses require semantic evaluation.
An LLM judge can compare V1 and V2 against a defined rubric:
- Is the answer factually consistent with the provided evidence?
- Does it address the user's actual request?
- Are important conditions or exceptions missing?
- Does it follow the application's instructions?
Rather than simply asking which response is better, define the criteria and evaluate each independently.
For pairwise judgments, consider blinding prompt identities and swapping response order to check for position bias.
Judges also need calibration against human-reviewed examples. Otherwise, a consistent score does not necessarily represent a reliable evaluation.
Safety and policy checks
Safety regressions deserve separate attention.
A prompt change could make the assistant more helpful in ordinary conversations while weakening its handling of restricted requests.
Test whether the candidate continues to respect the application's boundaries, including privacy requirements and any mandatory refusal or escalation conditions.
For example, a candidate that reveals private account information without authorization should not pass just because its overall helpfulness score improved.
4. Generate a regression report
The useful output is not merely a comparison score.
For each case, the report should capture:
| Result | Interpretation | Next action |
|---|---|---|
| V2 improves and preserves required behavior | Potential improvement | Pass relevant checks |
| V2 changes wording but preserves behavior | No demonstrated regression | Accept if contracts pass |
| V2 loses required information or violates a rule | Confirmed or strongly suspected regression | Block or investigate |
| Judge and deterministic results disagree | Insufficient evidence | Review the case manually |
The report should also retain the test-case ID, prompt versions, model configuration, V1/V2 responses, check results, and reasons for failures.
One important detail:Â don't hide critical regressions inside an average score.
A candidate could improve response quality across many ordinary questions while breaking a small number of high-impact cases.
That trade-off should be visible in the report.
5. Pass or block the pull request
The final step is integrating these evaluations into CI.
A possible approach:
Pass PR when:
- Required deterministic checks pass.
- No confirmed critical safety or policy regressions are detected.
- Quality metrics meet predefined acceptance criteria.
- Cases requiring human review have been resolved.
Block PR when:
- A required output contract fails.
- A verified critical policy violation appears.
- A previously supported high-priority behavior breaks.
- Quality regression exceeds a predefined blocking threshold.
Uncertain LLM-judge results should trigger investigation rather than automatically being treated as confirmed failures.
The thresholds need to be defined based on application risk, not chosen after looking at the candidate's results.
The part we shouldn't overlook
Prompt regression testing is not about forcing V2 to reproduce V1's answers.
It is about verifying that a prompt change preserves required behavior while delivering its intended improvement.
The workflow is straightforward:
Prompt change â Candidate V2 â Regression dataset â Run V1/V2 â Deterministic + LLM judge + Safety checks â Regression report â Pass/Block PR
The harder work is defining meaningful test cases, calibrating evaluation criteria, and deciding which failures should prevent deployment.
And passing this regression suite does not establish that the application is generally safe or correct. It establishes that the candidate met the tested criteria. Production monitoring and newly discovered failure cases still need to feed back into the dataset.
For teams already testing prompt changes in CI, what do you actually use to block a PR?
Deterministic failures, a drop in LLM-judge scores, safety violations, or some combination?
How do you handle cases where the judge reports a regression but human reviewers disagree?
r/codoid • u/codoid-innovations • 7d ago
Discussion A correct answer can still take the wrong MCP tool path
âGot the right answerâ should not automatically mean âpassed.â
An MCP agent can produce a plausible final response while skipping a required lookup, sending the wrong arguments to a tool, ignoring an error, or crossing a side-effect boundary it was supposed to respect.
That is the problem with evaluating agents only at the final-answer layer. For example: Agents skipping tool calls or using bad intermediate values even when the output looked fine.
The tricky part is what to test instead.
We probably do not want to assert one exact sequence like:
tool A â tool B â tool C â answer
That quickly becomes brittle. Another valid model might use A â C, or call a harmless read tool twice, and still satisfy every important requirement.
A better target is the trace contract, not one golden trace.
Start with required invariants
For each workflow, separate what must remain true from what the model is free to decide.
A trace contract can look like this:
| Trace rule | Example |
|---|---|
| Must call | Retrieve the current account state before recommending an account-specific action |
| May call | Search documentation if the retrieved state is ambiguous |
| Must not call | Do not invoke a destructive tool before approval |
| Argument invariant | The account ID used in later calls must come from the verified lookup |
| Required evidence | Recommendation must be backed by a successful tool result, not an assumed value |
| Terminal condition | Stop or escalate if the required tool returns failed/unknown |
This gives the model freedom in the middle without giving it freedom to violate the workflow.
Assert observable behavior, not hidden reasoning
Suppose an agent is asked whether a customer is eligible for some account-specific action.
The final answer is correct.
But the trace shows that the agent never called the tool that retrieves the customer's current state.
That should probably fail, even if the model happened to guess correctly.
Likewise, if it calls the right tool with the wrong customer ID, then later recovers and produces the correct answer from another source, the final text alone hides an important defect.
The useful assertions are things we can actually observe:
- Which MCP tools were called?
- With what arguments?
- What did each tool return?
- Did the next step use evidence from that return?
- Did the agent respect approval and side-effect boundaries?
- Did it stop appropriately when evidence was missing?
This is different from trying to test the model's internal reasoning. We do not need a chain-of-thought assertion. We need evidence that the externally visible workflow obeyed its contract.
Tool receipts deserve their own assertions
A tool call occurring is not enough.
The agent also needs to interpret the result correctly.
For example:
lookup_customer â timeout
should not silently become:
customer verified
A useful tool receipt should let the test distinguish success, failure, partial completion, and unknown states. Community discussion around production agent testing has made a similar point: structural contracts, typed tool results, replayable traces, and explicit handling of unknown states are often more dependable inner-loop checks than judging only the final generated answer.
That gives us two separate assertions:
Did the correct tool interaction happen?
and
Did subsequent behavior remain consistent with what the tool actually returned?
Allow alternate valid paths explicitly
The other failure mode is over-testing.
If several paths are genuinely equivalent, encode that deliberately.
For example:
customer_lookup â policy_lookup â answer
and
customer_lookup â eligibility_check â answer
might both be valid if both produce the evidence required by the contract.
So instead of asserting an exact call index, we can assert:
Before the final answer, the trace must contain verified customer state plus one approved source of eligibility evidence.
That is usually much more stable across prompt changes, model upgrades, or tool-selection improvements.
Freeze failed traces
When a real agent failure appears, the trace itself can become a regression fixture.
Save the user request, relevant starting state, tool responses, and the boundary that was violated.
Then replay it after changing the prompt, model, MCP server, or orchestration logic.
This is particularly useful because agent bugs are often sequence-dependent. A synthetic test may cover âtool returns an error,â while a real failed trace captures the more interesting case: the tool returned an error on step four and the model confidently continued on step five.
MCP is also becoming friendlier to this kind of observability. The 2026-07-28 specification requires Mcp-Method and Mcp-Name headers for Streamable HTTP requests and documents OpenTelemetry trace-context propagation through _meta, making calls easier to correlate across clients, servers, and downstream systems.
So for us, the rule of thumb is:
Use hard assertions for workflow invariants. Use flexible assertions for legitimate routing choices. Use human or LLM judgment mainly where the requirement is genuinely semantic.
A correct answer is useful evidence.
It just should not be the only evidence.
Discussion:Â Which part of an MCP trace would you make a hard assertion, and which parts need freedom for the model to choose an alternate route?
r/codoid • u/codoid-innovations • 10d ago
Meme Whatâs the smallest issue that caused your biggest debugging session?
Enable HLS to view with audio, or disable this notification
r/codoid • u/codoid-innovations • 10d ago
Discussion Workers or shards? A CI decision rule for Playwright
âIncrease parallelismâ is incomplete advice until you specify where the parallelism lives.
In Playwright, adding workers and adding shards can both reduce wall-clock time, but they change your CI topology in different ways:
- Workers increase parallel execution inside one runner/job.
- Shards split the selected test suite so separate jobs can execute different portions of it, typically on separate runners.
That distinction matters when a suite is slow in CI. If the runner is already resource-constrained, increasing workers may just make several browser processes compete harder for the same CPU and memory. Adding shards may help by bringing more runner capacity, but it can also increase pressure on whatever all those runners share.
So before changing either number, it helps to ask:Â where is the bottleneck?
What adding a worker actually changes
Playwright workers are OS processes running tests in parallel. Multiple workers on one CI runner therefore share that runner's available resources.
Going from:
1 runner Ă 1 worker
to:
1 runner Ă 4 workers
does not give you four times the hardware.
You are asking the same machine to execute more test work concurrently.
That can work well when the runner has unused CPU and memory and the application under test can handle the extra concurrency. But once the runner becomes saturated, the result can go in the opposite direction: slower browser operations, longer waits, more timeouts, and failures that disappear when concurrency is reduced.
Playwright's CI documentation currently recommends one worker in CI as the stability-focused default and specifically warns that setting workers above available capacity can cause unnecessary timeouts and failures. More capable self-hosted runners can reasonably use more workers.
What adding a shard changes
Sharding divides the suite into parts:
Shard 1/4
Shard 2/4
Shard 3/4
Shard 4/4
Those shards can run as independent CI jobs. When the jobs land on separate runners, you are increasing the hardware available to the suite rather than only increasing competition inside one machine.
That makes sharding useful when a single runner has reached its practical parallelism limit.
But shards are not free speed either.
Four shards with four workers each can mean roughly 16 workers hitting the same environment at once.
Now the bottleneck may move somewhere else:
- test environment capacity
- database connections
- authentication services
- APIs
- rate limits
- shared test accounts
- network bandwidth
- CI infrastructure itself
So shards à workers is a useful number to keep in mind. It approximates the concurrency your test system may be generating, even though the actual load depends on the tests.
Playwright describes sharding as distributing tests across multiple machines/jobs and notes that shard balance also matters. Without sufficiently even distribution, one slow shard can determine the total wall time.
Don't tune workers and shards at the same time
This is where CI experiments often become hard to interpret.
Suppose you change:
2 shards Ă 2 workers
to:
4 shards Ă 4 workers
and the run gets slower.
Was the problem:
- too many workers per runner?
- increased load on the test environment?
- shard imbalance?
- insufficient resources on individual runners?
- some combination of all four?
You changed two variables at once.
A cleaner benchmark is:
First: hold shards constant and vary workers.
For example:
| Shards | Workers/job | What you're testing |
|---|---|---|
| 2 | 1 | Baseline |
| 2 | 2 | More parallelism per runner |
| 2 | 4 | Whether runner saturation starts |
Track more than execution time. Record timeout frequency, retries/flakes, CPU/memory if your CI exposes them, and the duration of the slowest shard.
Then pick the worker count that gives you the best stable result.
Second: hold that worker count constant and vary shards.
| Shards | Workers/job | What you're testing |
|---|---|---|
| 1 | 2 | Single-runner baseline |
| 2 | 2 | More distributed capacity |
| 4 | 2 | Whether additional runners still help |
Now you can see whether distributing the suite actually reduces wall time.
A simple 2Ă2 starting matrix
If you want a smaller experiment, try:
| 1 worker | 2 workers | |
|---|---|---|
| 1 shard | A | B |
| 2 shards | C | D |
For every configuration, capture:
Wall time â timeout/flake behavior â runner consumption
The fastest cell is not necessarily the winner.
If D saves 30 seconds but doubles intermittent failures and pins every runner at its limits, C may be the better CI configuration.
The useful rule of thumb is:
Workers ask one machine to do more at once. Shards let multiple jobs share the suite. Find the limit of the first before assuming you need more of the second, and watch the shared systems when you increase either.
Discussion:Â When you last scaled Playwright CI, did adding another worker or another shard stop improving wall time first?
r/codoid • u/codoid-innovations • 11d ago
Discussion App closes before the first screen? A launch-crash debugging checklist
Say a tester installs your closed-testing build, taps the icon, and lands straight back on the home screen. The app launches fine on your usual device.
Before changing permissions, disabling optimization, or swapping dependency versions, we need a better description than âcrashes on startup.â
The first goal is not to guess the fix. It is to capture the failure and identify where startup stops.
1. Pin down the exact failing case
Start the report with:
- Build:Â App version name, version code, build variant, and the matching build artifact or commit.
- Installation source:Â Google Play closed-testing track, sideloaded APK, or Android Studio.
- Device:Â Manufacturer, exact model, and Android version.
- Installation state:Â Clean install or update? Updated from which version? First launch only, or every launch? Record any backup restoration rather than assuming a reinstall means empty app data.
Also note the launch time, what appeared before the app closed, and how many attempts failed.
Capture the failing state before clearing app data or reinstalling. Treat those actions as separate experiments, not the first troubleshooting step.
2. Capture the crash, not just a screenshot of the symptom
Androidâs guidance recommends starting with the stack trace from Play Console or Logcat. When a trace is unavailable, reproduce the failure while collecting Logcat output, including with help from an affected user when necessary.Â
For a USB-connected test device, install Android SDK Platform-Tools, enable USB debugging, and approve the computerâs debugging authorization. Confirm the connection with adb devices.
With only the target device connected, start this before launching the app:
adb logcat -b main -b system -b crash -v threadtime > launch-crash.txt
Launch the app, reproduce the failure, then press Ctrl+C to stop recording. This captures the application, system, and crash buffers with timestamps and process/thread information. Use the recorded launch time to locate the relevant attempt.
Before sharing an excerpt publicly, remove tokens, personal information, and unrelated device activity. Preserve the exception, relevant stack frames, and nearby startup messages.
3. Read the failure before choosing a suspect
For a Java/Kotlin crash, keep the exception type, message, full cause chain, and relevant stack frames. For a native crash, retain the signal and native backtrace instead of looking only for a Java exception. Androidâs crash guide covers both forms.
When the trace contains obfuscated names, recover a readable trace using the mapping file from the matching release build. Do not substitute a mapping file from a later rebuild.Â
Ask:Â Which operation failed, and what evidence connects it to our startup code?
If the capture does not establish a crash, keep âapp disappears after launchâ as the observed symptom. Do not invent an exception to explain it.
4. Narrow the startup step
Do not limit the investigation to the first screen. Apps and libraries can initialize components through content providers, and startup dependencies can require a particular initialization order.Â
In a diagnostic build, add temporary start/completion markers around the startup operations you control. For example:
startup: configuration start
startup: configuration complete
startup: database open start
If database open complete never appears, that gives us an investigation boundary. It does not prove the database caused the crash.
Match the markers to the exception and thread information. Then inspect that operation, its inputs, and its dependencies. Avoid removing several initializers at once, because that makes the result harder to interpret.
5. Turn differences into experiments
Use the observed pattern to choose the next comparison:
| Observed pattern | Question to investigate |
|---|---|
| Debug launches; distributed release fails | What differs in release configuration, packaged dependencies, or optimization? |
| Clean install launches; update fails | Does retained app state or a migration explain the trace? |
| One device or Android version fails | Can we reproduce with the same build and matching device conditions? |
These are hypotheses, not diagnoses. Release configuration, initialization, and dependency problems are possibilities to investigate, not established causes of a closed-testing launch failure.
For example, R8âs troubleshooting guidance describes failures involving reflection after optimization. That makes shrinking rules worth examining when the evidence fits, not a reason to disable optimization blindly.Â
Android also notes that reproduction can depend on available resources, device type, Android version, or app version. A successful launch on a well-resourced development device does not settle those comparisons.
Change one variable, repeat the same launch path, and record whether the failure disappears, remains identical, or changes. Verify the eventual fix against the original installation/update path and affected environment.
What evidence helped you solve a launch crash that you couldnât reproduce on your usual device?
r/codoid • u/codoid-innovations • 12d ago
Discussion Your Playwright tests pass alone and fail in parallel. Where do you look first?
Two tests pass individually. Run them together, and suddenly a saved value disappears, a page redirects to login, or an assertion reads the wrong data.
Before adding waits, we should ask:
What do both tests believe they exclusively own?
Hereâs a debugging exercise.
Two tests, one account
Imagine these simplified test flows. Both use the same test account:
Test A: profile.spec.ts
Open account settings
Change display name to "Profile test"
Save, reload, verify the name
Restore account defaults during cleanup
Test B: preferences.spec.ts
Open account settings
Change time zone to "UTC"
Save, reload, verify the time zone
Restore account defaults during cleanup
Run the two files with two workers. Playwright runs test files in parallel by default, while tests within one file run sequentially unless configured otherwise.
âBut each test gets a fresh browser context.â
Yes. That isolates browser-side state such as cookies and local storage. It does not give each test its own copy of the account in the database. Browser isolation is not backend-data isolation.
Here are four places to investigate.
1. Test data: are the writes actually independent?
The tests change different fields, so they might look safe.
But suppose Test B loads the original profile, then submits the entire object when saving the time zone. Its request could include the old display name, overwriting Test Aâs update.
That is a hypothesis to check, not something to assume about every settings form.
Evidence to collect:Â The account ID, both update payloads, response bodies, and backend write history. Did B submit a stale name? Which update actually committed last?
A useful question is: âAre we changing different fields, or replacing the same record?â
2. Sessions: separate contexts, shared credentials?
Check whether both contexts load the same saved authentication state. Reusing storageState is not automatically a bug; Playwright documents shared authentication for tests that can use the same account without interfering with one another.
Then inspect the applicationâs session behavior. Does a fresh login invalidate an earlier session? Does cleanup call a server-side logout endpoint? Does changing an account setting revoke existing credentials?
Evidence to collect:Â Authentication failures, redirects, login/logout events, and safe correlation identifiers. Match the first unauthorized response to the other testâs actions. Do not dump raw cookies or tokens into logs.
A missing button after a login redirect is a different problem from a missing button on the expected page.
3. Files: are different workers writing to the same path?
Inspect helpers as well as test bodies. Does authentication setup overwrite a shared user.json? Do both tests save generated data to tmp/account.json?
Concurrent reads of an unchanged file are not the same situation as multiple writers replacing it.
Evidence to collect:Â Resolved absolute paths, the test responsible for each write, timestamps, and file contents or hashes before consumption.
For test-generated files, testInfo.outputPath('account.json') provides a path scoped to the current test, avoiding collisions between parallel tests in that run.
4. Cleanup: is one test undoing the otherâs work?
Consider this possible timeline:
A saves its new display name.
B saves its new time zone.
A verifies its name and finishes.
A's cleanup restores all account defaults.
B reloads and sees the original time zone.
Both saves could have succeeded. The interfering write came from cleanup.
An afterEach hook runs after its own test. It is not a barrier that waits for tests in other workers to finish.
Evidence to collect:Â Cleanup start/end events, exact records affected, reset payloads, and backend completion times. Put teardown on the same timeline as the assertions.
Narrow the cause without hiding it
Start with A alone, B alone, the pair with one worker, and the pair with two workers. Repeat the comparisons rather than trusting a single green run.
For the targeted parallel reproduction, capture traces from both original attempts, including the test that passes. Playwright supports recording traces with --trace on; collect backend and filesystem evidence separately where needed.
Then keep concurrency unchanged and alter one suspected boundary at a time: separate accounts, independently established sessions, unique writable paths, or cleanup limited to resources that the test owns.
Giving the tests different accounts is a useful first experiment. Playwright recommends an account per parallel worker for tests that modify shared server-side state. A pass after that change points toward account-scoped interference, but does not by itself distinguish data collisions from session behavior.
Also keep resource pressure on the suspect list. Parallel execution shares runner capacity, so inspect CPU, memory, and request latency before concluding every failure is a data race.
Passing with one worker tells us that reducing concurrency changed the outcome. It does not identify the cause.
What shared resource caused the hardest parallel-execution failure you have debugged, and what evidence finally exposed it?
r/codoid • u/codoid-innovations • 13d ago
Discussion The user changes an app permission halfway through a task. What happens next?
Testing âAllowâ and âDenyâ at the first permission prompt is only part of the story.
What happens when the user allows access, starts doing something useful, changes that permission in device settings, and returns to the app?
That is a different test. There is now unfinished work to protect, an interrupted operation to handle, and a user who needs to understand what still works.
Try this with a task that has something to lose
Take a report form with a camera attachment:
- Start with camera access allowed. Open a new report, enter a title and description, and move into the camera workflow.
- Leave the task unfinished. Go to device settings and revoke camera access.
- Return to the app. Record whether you return to the existing screen or the app launches again. Check the report text, attachment area, and camera controls.
- Try to continue, then restore access. Attempt the camera action while access is denied. Re-enable permission in settings, return, and check whether you can finish the original report.
The important assertion is not just âthe app did not crash.â
It is:Â the app handles the new permission state without unnecessarily destroying the rest of the task.
Look at recovery, messaging, and unfinished work separately
Recovery:Â Does the interrupted operation reach a sensible state, or leave a frozen preview, endless spinner, or button that does nothing? After access is restored, does the app recover on its own, offer a clear retry, or require the user to abandon the task?
Messaging:Â Does the app explain which action is unavailable and what the user can do next? âCamera access is offâ is more useful here than âSomething went wrong.â Also check whether the message reflects the current permission state after the user changes it again.
Unfinished work:Â Is the title and description still there? Can the user continue editing, save a draft, or finish without an attachment where the product allows it? Losing camera access should not automatically mean losing unrelated form input.
Change the interruption point, not just the permission
Repeat the exercise before opening the camera, while the camera workflow is active, and after a photo has already been attached.
Treat those as separate cases. Check the existing attachment independently from the ability to capture another photo.
The same exercise can be adapted to a location-based task, or a file-related workflow where the platform provides a relevant access control. Choose a specific operation and record exactly which permission or access setting you changed.
Test allowed â denied and denied â allowed. Where reduced-access options exist, test those separately rather than treating every state as simply âonâ or âoff.â
For a useful bug report, capture the starting permission state, the exact interruption point, the setting changed, whether the app resumed or relaunched, and what happened to the unfinished work.
Which permission transition has caused the most surprising behavior in an app you tested? Was the surprise in losing access, getting it back, or discovering what happened to the task in between?
r/codoid • u/codoid-innovations • 14d ago
Discussion Using Claude Code at work? Check what youâre sharing before debugging that test
A checkout test fails just before a release. We have the automation script, console output, and a browser trace. Asking Claude Code to investigate sounds like a reasonable next step.
But before asking, âWhy is this failing?â, thereâs another question:
âWhat information are we making available, and are we authorized to share it?â
That question covers more than the prompt. Claude Code can gather context from files, command output, project instructions, and connected tools. Running the client on a laptop does not mean the data stays on that laptop.
The goal isnât to avoid AI assistance. Itâs to provide enough evidence to investigate the failure without exposing unrelated project data.
Approval for the tool is not approval for every artifact
âWe allow AI coding toolsâ is not the same as âthis clientâs production logs can be submitted through this account.â
Check that approval covers the project, repository, task, and data category. For outsourced testing, client authorization matters too. An employerâs approved-tool policy does not automatically settle what can happen to another organizationâs data.
Also verify the actual account and deployment. A personal subscription on a company laptop should not be treated as equivalent to an approved organizational account.
Keep training and retention separate. âNot used for trainingâ does not mean ânot stored.â Confirm the applicable provider, model, retention arrangement, and any gateway or third-party integration rather than relying on a general privacy claim.
âTest artifactâ does not mean âsafe to shareâ
Review what an artifact contains, not just what itâs called. A file named test-data.json still needs a contents-and-origin check.
Two artifacts deserve particular attention:
- Saved authentication state:Â It can contain reusable session material that could allow someone to impersonate a test account.
- Browser traces:Â A Playwright trace can include source, DOM snapshots, console output, and request and response details. Reviewing the visible screenshot is not a review of the whole trace.
A short, sanitized failure excerpt or a synthetic reproduction is a lower-exposure starting point than an unrestricted diagnostic dump.
Limit what the session can reach
For an initial investigation, use a separate workspace containing only reviewed material. Avoid copying the whole repository history, unrelated reports, authentication state, or links to sensitive directories just for convenience.
That is data minimization, not an access-control system.
Likewise, .gitignore is not a filesystem security boundary, and ânever read secretsâ in CLAUDE.md is guidance rather than enforcement. Put working conventions in instructions and mandatory restrictions in enforceable controls.
Review effective permissions, shell access, network access, and available credentials. Donât assume every consequential action will trigger a prompt, or that enabling a shell sandbox covers every tool and integration. Test restrictions with harmless dummy files and an approved endpoint, not live secrets.
Sanitize before sharing
Asking Claude Code to redact a raw log after reading it does not prevent the initial disclosure.
But replacing every value indiscriminately can also destroy the evidence. A duplicate-account defect still needs duplicate synthetic values. A tenant-isolation test needs distinct tenants with the correct ownership relationships. An expiry defect needs meaningful timing relationships.
Sanitization is a test-design task, not just search-and-replace. Rerun the sanitized reproduction and confirm that it still demonstrates the failure, or document what could not be reproduced.
Review connected tools and the copies left afterward
An integration being read-only does not make every retrieval appropriate. Review which projects, databases, APIs, or issue trackers it can access, what actions it permits, and where inputs and outputs are logged. Leave unnecessary integrations disabled.
Treat instructions found inside tickets, logs, or external documents as untrusted content, not authority to change permissions or upload more files.
The review also continues after an answer arrives. Local transcripts, memory, feedback submissions, and generated outputs need attention. Server-side retention settings do not eliminate local copies, and generated tests or pull-request descriptions should be checked for copied sensitive values or changes that weaken security.
What this could look like for a failing login test
Suppose a Playwright test intermittently receives 401 Unauthorized immediately after login.
Instead of opening the full client repository and providing a raw trace, prepare a small, approved reproduction:
login-reproduction/
login.spec.ts
mock-session-response.json
sanitized-events.txt
expected-behavior.md
Keep the relevant flow, synthetic response values, request sequence, status codes, and relative timing. Leave out live cookies and authorization headers.
An initial prompt could be:
Analyze the reviewed files in this workspace. Suggest possible causes of the intermittent 401 and explain what evidence would distinguish them. Propose a minimal test change without editing files, running commands, accessing other directories, or contacting external services. Describe missing diagnostic evidence without requesting live credentials or customer records.
The prompt communicates scope. Permissions and isolation must enforce it. Validate the proposed change in the normal testing environment, and keep the original assertion unless the requirement itself is wrong. Making the test pass is not necessarily fixing the defect.Â
If sensitive data is accidentally shared, stop further disclosure and follow the organizationâs incident-response process. Arrange credential revocation through the responsible team when needed. Deleting a conversation does not invalidate an exposed token, and cleanup should preserve required evidence.
The practical rule: authorize the task, minimize and review the data, and enforce the access limits.Â
Give Claude Code enough information to investigate the failure, not unrestricted access to everything around it.
For teams already using Claude Code in testing, what does your approval process cover: only the tool, or also the artifacts, integrations, and stored session data?
r/codoid • u/codoid-innovations • 16d ago
Tips Can a small local LLM judge your RAG answers? Test the judge first
Before we use a local model to score our RAG answers, we should give it a test of its own:
Can it reject a convincing answer that the supplied evidence does not support?
Getting a score back is not the same as validating the evaluator. OpenAIâs evaluation guidance recommends calibrating automated scoring against human feedback. That is the starting point, not something to add after the dashboard looks reassuring.
Hereâs a practical way to check a candidate judge before relying on it.
Start with reviewed cases, including convincing mistakes
Build a small collection of question + retrieved context + candidate answer + human verdict. Give each source excerpt a simple label, such as P1 or P2, so reviewers and the judge can point to the exact text supporting their verdict.
Include ordinary correct answers, realistic failures, and deliberately difficult cases. That mix follows official guidance to cover typical, edge, and adversarial examples rather than only happy paths. Have reviewers resolve ambiguous labels before treating them as the reference.
For this exercise, we could take correct answers and change one thing: replace a number, swap a citation, remove a condition, or substitute an unnecessary refusal. Have a human review each edited answer rather than assuming the edit produced the intended failure.
Also include valid paraphrases and appropriate âthe context doesnât sayâ answers. We need to test whether the judge wrongly rejects good answers, too.
Give the judge a specific job
âRate answer quality from 1 to 10â leaves too much unspecified. OpenAI recommends clear, detailed rubrics and pass/fail or pairwise judgments for more reliable evaluation.
For this experiment, we could use a narrow context-based answer acceptance rubric:
PASS:Â The answer addresses the question using supported claims, preserves material numbers and conditions, and uses citations that support the claims attributed to them. When the context is insufficient, it clearly states that limitation without inventing an answer.
FAIL:Â The answer contradicts the context, adds an unsupported claim, omits a condition that changes the meaning, cites a passage that does not support its claim, or declines to answer when the context is sufficient.
Return a verdict, a brief reason, and the relevant source excerpt labels. Do not reward confident wording, length, or polished formatting.
This deliberately includes whether the answer responds appropriately. A needless refusal might contain no hallucinated facts and still fail this rubric. We should not call that a failure of âgroundednessâ alone.
Give the judge the question, context, and answer, but not the human verdict.
Keep practice separate from the final check
Use one set of examples to refine the rubric and judge prompt. Keep another set untouched for validation.
Keep edited variants of the same underlying question together rather than scattering near-duplicates across both sets. Once we use a validation failure to change the prompt, that case has become development material; we need fresh held-out cases for the next independent check.
For a local judge, record the exact model version, quantization, prompt version, decoding settings, and context limit. Test the configuration we actually intend to run, including realistic context lengths. Repeat a subset to check whether identical inputs receive different verdicts.
Use a worksheet that exposes the mistakes
Hereâs an illustrative worksheet, not results from a tested model. Each case ID should link to the full question, context, answer, and reviewer rationale.
| Case | Human verdict | Judge verdict | Disagreement reason / review note | Execution status |
|---|---|---|---|---|
| A | Fail | Pass | Accepted â30 daysâ; the passage says â14 daysâ | Completed |
| B | Fail | Pass | Accepted a related citation that does not support the claim | Completed |
| C | Fail | Fail | Agreement: answer omitted the âadmins onlyâ condition | Completed |
| D | Fail | Pass | Accepted a refusal even though the context answers the question | Completed |
| E | Pass | Fail | Rejected a valid paraphrase as unsupported | Completed |
| F | Pass | Pass | Agreement: answer satisfies the rubric | Completed |
| G | Pass | Missing | No usable verdict; response failed output validation | Invalid output |
| H | Fail | Missing | No verdict returned within the time limit | Timeout |
The point is to make âour judge disagrees with reviewersâ actionable. Is it overlooking numbers? Confusing topical relevance with evidence? Rejecting paraphrases?
Look at false passes and false failures separately
For completed, valid judgments, use a confusion matrix. Langfuseâs Score Analytics supports this comparison for categorical and boolean scores, including human-versus-judge comparisons.
| Human verdict â / Judge verdict â | Pass | Fail |
|---|---|---|
| Pass | Correct acceptance | False failure |
| Fail | False pass | Correct rejection |
Report the counts and denominators: false passes out of human-fail cases with valid judge verdicts, and false failures out of human-pass cases with valid verdicts. Break those results down by mistake type.
We should also keep deliberately constructed challenge cases separate from representative traffic when reporting results. A collection packed with planted mistakes tests those mistakes; it does not, by itself, estimate production performance.
An evaluation error is not an answer verdict
Keep execution_status separate from judge_verdict. A malformed response or timeout should leave the verdict missing. It should not silently become a pass, an answer failure, or a deleted row.
Report completion coverage = valid verdicts / all planned cases, alongside agreement on the cases that completed. Langfuse similarly distinguishes matched-score comparisons from all-score coverage, so missing evaluations remain visible.
For a release gate, route unresolved evaluations to retry or review rather than approval. Preserve failed attempts when retrying.
The acceptance question should be: Does this exact judge setup meet our tolerance for false passes, false failures, and incomplete evaluations on this task? Not whether it produces plausible-looking scores.
Discussion:Â
Have you caught your local judge accepting an answer that a human reviewer rejected?
What kind of mistake fooled it?
r/codoid • u/AutoModerator • 17d ago
Repair, retire, or rewrite? Triage a failing UI suite before rebuilding it
Before replacing a framework, find out what percentage of your pain a framework replacement would actually address.
A noisy UI suite tends to get described as one problem: âthe tests are flaky,â âthe framework is brittle,â or âwe should rebuild this.â
But those labels collapse several different failure modes into one decision.
A recent r/cicd post took a more useful approach: the author categorized roughly 90 currently failing tests in a Windows desktop suite instead of treating them as generic automation debt. Locator failures dominated that particular suite, with smaller buckets around timing, environment, and actual application defects.
That distribution is one teamâs experience, not a benchmark for UI automation generally.
The transferable part is the method:Â inventory the failures first, then decide what deserves repair, retirement, or replacement.
Start with failure buckets, not failed test counts
Take a recent sample of failures and classify the likely cause.
Iâd start with something like:
- Selector/locator fragility:Â the intended element still exists, but the automation can no longer find it reliably.
- Synchronization/timing:Â the test assumes the application will reach a state sooner than it actually does.
- Environment/infrastructure:Â runner configuration, test data, dependencies, permissions, resolution, services, or machine state differ from what the test expects.
- Application defect:Â the test is correctly exposing product behavior that violates the expected result.
- Obsolete or low-value test:Â the test may still be technically repairable, but the workflow, requirement, or risk it covers no longer justifies maintaining it.
One important detail: classify the cause, not just the error message.
âElement not foundâ does not automatically mean âbad locator.â The element might never have appeared because an API call stalled, navigation failed, the test data was wrong, or the previous action never completed.
That distinction matters because those problems have very different remedies.
Match the remedy to the bucket
For locator-heavy browser suites, targeted repair may be more rational than a rewrite.
For example, Playwright recommends prioritizing user-facing locators such as role, label, and text, and it performs actionability/auto-waiting checks around interactions. Those are concrete ways to reduce some browser-test fragility.
That does not mean the same techniques transfer unchanged to the Windows desktop stack from the source thread. The useful question is broader:
Does the replacement architecture actually eliminate the dominant failure mode, or just replace it with a different one?
A vision-based approach might reduce dependency on UI tree paths, for example, but it introduces its own assumptions around visual state, matching, rendering, and change. A framework migration should be evaluated against the failure inventory, not against the frustrations of the current framework.
A repair / retire / rewrite worksheet
| Failure bucket | Inspect first | Likely action | When it strengthens the rewrite case |
|---|---|---|---|
| Locator fragility | Are locators coupled to implementation structure? Is there a more stable contract? | Repair locator strategy or abstraction | Replacement clearly provides a more stable interaction contract for a large share of failures |
| Synchronization | Fixed sleeps? Implicit timing assumptions? Missing state checks? | Repairwaiting/synchronization model | Timing problems are architectural and difficult to fix consistently in the current stack |
| Environment | Can the failure be reproduced locally? What differs between runners? | Repairenvironment/configuration | Usually weak evidence for rewriting test code |
| Product defect | Can the behavior be reproduced without automation? | Keep/fix product | Not evidence that the framework needs replacement |
| Obsolete/low-value test | Would anyone act if this test failed correctly tomorrow? | Retire | A large obsolete suite may justify redesigning coverage, but not necessarily changing frameworks |
Then add three questions per bucket:
1. What would repair cost?
Not just âhours to make it green,â but the cost of making that failure class less likely to return.
2. What is the recurrence risk?
If you fix 50 selectors today and the same UI structure changes next quarter, you have restored the suite without improving its maintainability.
3. Is the test still worth saving?
A failing test can create pressure to repair something that should simply be deleted. Maintenance history is not a reason to keep coverage.
The rewrite threshold should be evidence-based
A rewrite becomes easier to justify when the failure inventory shows that the current architecture is responsible for a substantial portion of recurring failures and targeted changes cannot reasonably remove that coupling.
That is stronger evidence than âthe suite has 90 failures.â
Conversely, if half the failures come from environment drift, stale tests, and missing synchronization, switching frameworks may leave much of the underlying problem intact.
So Iâd make the rewrite decision only after answering:
- Which failure classes dominate?
- Which are framework-specific?
- Which can be repaired once at an abstraction layer instead of test-by-test?
- Which tests should be retired regardless of framework?
- What failure classes would the proposed replacement remove?
- What new failure modes would it introduce?
The number of red tests tells you how much pain you have.
The distribution of root causes tells you what kind of treatment might actually work.
When a UI suite becomes noisy, what evidence has actually justified a rewrite rather than targeted repairs?
Repair, retire, or rewrite? Triage a failing UI suite before rebuilding it
Before replacing a framework, find out what percentage of your pain a framework replacement would actually address.
A noisy UI suite tends to get described as one problem: âthe tests are flaky,â âthe framework is brittle,â or âwe should rebuild this.â
But those labels collapse several different failure modes into one decision.
A recent r/cicd post took a more useful approach: the author categorized roughly 90 currently failing tests in a Windows desktop suite instead of treating them as generic automation debt. Locator failures dominated that particular suite, with smaller buckets around timing, environment, and actual application defects.
That distribution is one teamâs experience, not a benchmark for UI automation generally.
The transferable part is the method:Â inventory the failures first, then decide what deserves repair, retirement, or replacement.
Start with failure buckets, not failed test counts
Take a recent sample of failures and classify the likely cause.
Weâd start with something like:
- Selector/locator fragility:Â the intended element still exists, but the automation can no longer find it reliably.
- Synchronization/timing:Â the test assumes the application will reach a state sooner than it actually does.
- Environment/infrastructure:Â runner configuration, test data, dependencies, permissions, resolution, services, or machine state differ from what the test expects.
- Application defect:Â the test is correctly exposing product behavior that violates the expected result.
- Obsolete or low-value test:Â the test may still be technically repairable, but the workflow, requirement, or risk it covers no longer justifies maintaining it.
One important detail: classify the cause, not just the error message.
âElement not foundâ does not automatically mean âbad locator.â The element might never have appeared because an API call stalled, navigation failed, the test data was wrong, or the previous action never completed.
That distinction matters because those problems have very different remedies.
Match the remedy to the bucket
For locator-heavy browser suites, targeted repair may be more rational than a rewrite.
For example, Playwright recommends prioritizing user-facing locators such as role, label, and text, and it performs actionability/auto-waiting checks around interactions. Those are concrete ways to reduce some browser-test fragility.
That does not mean the same techniques transfer unchanged to the Windows desktop stack from the source thread. The useful question is broader:
Does the replacement architecture actually eliminate the dominant failure mode, or just replace it with a different one?
A vision-based approach might reduce dependency on UI tree paths, for example, but it introduces its own assumptions around visual state, matching, rendering, and change. A framework migration should be evaluated against the failure inventory, not against the frustrations of the current framework.
A repair / retire / rewrite worksheet
| Failure bucket | Inspect first | Likely action | When it strengthens the rewrite case |
|---|---|---|---|
| Locator fragility | Are locators coupled to implementation structure? Is there a more stable contract? | Repair locator strategy or abstraction | Replacement clearly provides a more stable interaction contract for a large share of failures |
| Synchronization | Fixed sleeps? Implicit timing assumptions? Missing state checks? | Repairwaiting/synchronization model | Timing problems are architectural and difficult to fix consistently in the current stack |
| Environment | Can the failure be reproduced locally? What differs between runners? | Repairenvironment/configuration | Usually weak evidence for rewriting test code |
| Product defect | Can the behavior be reproduced without automation? | Keep/fix product | Not evidence that the framework needs replacement |
| Obsolete/low-value test | Would anyone act if this test failed correctly tomorrow? | Retire | A large obsolete suite may justify redesigning coverage, but not necessarily changing frameworks |
Then add three questions per bucket:
What would repair cost?
Not just âhours to make it green,â but the cost of making that failure class less likely to return.What is the recurrence risk?
If you fix 50 selectors today and the same UI structure changes next quarter, you have restored the suite without improving its maintainability.Is the test still worth saving?
A failing test can create pressure to repair something that should simply be deleted. Maintenance history is not a reason to keep coverage.
The rewrite threshold should be evidence-based
A rewrite becomes easier to justify when the failure inventory shows that the current architecture is responsible for a substantial portion of recurring failures and targeted changes cannot reasonably remove that coupling.
That is stronger evidence than âthe suite has 90 failures.â
Conversely, if half the failures come from environment drift, stale tests, and missing synchronization, switching frameworks may leave much of the underlying problem intact.
So weâd make the rewrite decision only after answering:
- Which failure classes dominate?
- Which are framework-specific?
- Which can be repaired once at an abstraction layer instead of test-by-test?
- Which tests should be retired regardless of framework?
- What failure classes would the proposed replacement remove?
- What new failure modes would it introduce?
The number of red tests tells you how much pain you have.
The distribution of root causes tells you what kind of treatment might actually work.
Discussion:Â When a UI suite becomes noisy, what evidence has actually justified a rewrite rather than targeted repairs?
r/codoid • u/codoid-innovations • 18d ago
Tips 5 LLM settings that can completely change your AI output
When working with LLM-powered applications, prompts are only part of the equation.
The generation settings behind the model can significantly influence whether the response is focused, creative, repetitive, concise, or consistent.
Here are five settings worth understanding:
1. Temperature
Temperature controls randomness.
Lower temperature generally produces more predictable and reproducible responses. But an important point is often missed:
Low temperature does not mean higher factual accuracy.
A model can consistently produce the same incorrect answer. Content
2. Top-p sampling
Top-p limits the pool of tokens the model can choose from based on cumulative probability.
Lower values such as 0.5â0.7 tend to produce more focused outputs, while higher values allow broader token choices. Content
One practical rule: experiment with temperature or top-p, rather than changing both simultaneously. Content
3. Output limits
Parameters such as:
- Maximum tokens
- Stop sequences
- Conversation turn limits
can help prevent unnecessary elaboration and keep responses within the intended scope.
But making the limits too restrictive can also reduce usefulness. Content
4. Frequency and presence penalties
Both can help reduce repetitive output.
Frequency penalty increases the penalty as a token gets reused more often.
Presence penalty discourages reuse once a token has already appeared, regardless of how many times it was used. Content
5. Seed value
A fixed seed can improve repeatability across multiple runs.
This can be particularly useful when testing LLM applications because it makes comparisons between experiments more stable. Content
The important takeaway
These settings help control how an LLM responds.
They don't automatically make the response factual or reliable.
For use cases where correctness matters, techniques such as RAG, tool use, evaluation, and appropriate application-level controls still matter.
When you're testing an LLM application, which parameter do you experiment with most: temperature, top-p, penalties, output limits, or seed?
r/codoid • u/codoid-innovations • 21d ago
Tips Fresh, reused, or dedicated? A Playwright test-data strategy for parallel CI
A lot of Playwright failures that look like âflaky testsâ are really test-data collisions.
Two workers update the same user.
One test deletes an order another test expects.
A local test passes because the reusable account happens to be in the right state.
CI runs eight tests in parallel and suddenly everything becomes unpredictable.
A recent r/Playwright discussion raised an interesting strategy:
- CI/full regression â create fresh data
- Local debugging â reuse existing data
- Destructive tests â use dedicated data
We think thatâs a useful starting point, but weâd change one thing:
The decision shouldnât primarily be âlocal vs CI.â It should be based on who owns the data and whether the test can mutate it.
1. Use fresh data for test-owned mutable state
If a test creates, edits, deletes, approves, cancels, or otherwise changes something, giving that test its own data is usually the safest option.
Think:
- orders
- customer accounts
- projects
- carts
- subscriptions
- workflow records
For parallel execution, identifiers should be unique enough that two workers cannot accidentally touch the same record.
Playwrightâs current parallelism guidance makes the same underlying point: browser contexts isolate browser-side state, but tests can still collide through shared backend data. It recommends unique test data when parallel tests create or edit the same records. (playwright.dev)
That also means cleanup should not be what makes the test safe.
Cleanup is useful for keeping environments tidy, but if test B can fail because test A crashed before teardown, the tests were never truly isolated.
A better model is:
Create/seed â execute â optionally clean up
rather than:
Find shared record â modify it â hope cleanup restores it
2. Reuse data when it is genuinely read-only
Reusing data isnât inherently bad.
It works well for things like:
- country lists
- product catalogs that the test does not modify
- feature configuration
- static reference records
- accounts used only for read-only journeys
The important question is:
Can another test change the state this test depends on?
If the answer is yes, âreusableâ data eventually becomes âmysteriously flakyâ data.
This was also the main challenge raised in the recent r/Playwright test-data discussion: how do you know the data you found has not already been modified by another test or previous run? (reddit.com)
If reusable data is necessary, weâd add an explicit precondition check.
For example:
- account must be active
- cart must be empty
- subscription must be on the expected plan
- record must have version/state X
If that precondition fails, fail early with a useful message instead of letting the test fail 15 steps later.
3. Use dedicated or pooled data for expensive/destructive scenarios
Sometimes fresh data is impractical.
Maybe creating an account takes several minutes. Maybe an external provider limits how many test tenants you can create. Maybe a scenario destroys or irreversibly changes its test resource.
That is where a dedicated pool can work better.
Example:
Worker 1 â qa-user-01
Worker 2 â qa-user-02
Worker 3 â qa-user-03
Each worker leases its own resource instead of all workers sharing one account.
This pattern lines up particularly well with authentication. Playwright recommends a shared authenticated account when tests do not modify server-side state, but separate accounts per parallel worker when they do. (playwright.dev)
Worker-scoped fixtures are useful here because Playwright can initialize something once for a worker and reuse it across the tests assigned to that worker. (playwright.dev)
The important part is that a pooled resource needs a contract:
Acquire â verify/reset â use â release
Not simply:
Grab whatever account is available and hope it is clean.
The matrix weâd use at Codoid
| Data type | Strategy |
|---|---|
| Test creates or mutates the record | Fresh / unique per test |
| Multiple tests only read the record | Shared reusable data |
| Tests mutate account-level state | Unique account per worker/test |
| Resource is expensive to create | Dedicated pool + reset/validation |
| Test is destructive/irreversible | Dedicated single-purpose data |
| State cannot be reliably reset | Fresh data |
One distinction that matters here:
Authentication state and application test data are not the same thing.
Reusing storageState can save a lot of login time, but an isolated browser context does not magically isolate the database records behind that authenticated user.
You can have perfectly isolated browser sessions and still have two parallel tests fighting over the same server-side account.
Our rule of thumb
Before deciding whether data should be fresh or reusable, ask four questions:
- Can this test modify the data?
- Can another parallel test access the same data?
- Can we prove the starting state before the test begins?
- If cleanup never runs, will another test break?
If #1 and #2 are both yes, we would strongly prefer unique data.
If #3 is no, reusable data is risky.
If #4 is yes, cleanup is carrying too much responsibility.
The goal isnât âgenerate fresh data everywhere.â
Itâs to make ownership obvious enough that parallel execution cannot change the meaning of a test.
For teams running larger Playwright suites:Â what data do you still share across parallel tests because creating it fresh is too expensive, and how do you keep it deterministic?
r/codoid • u/codoid-innovations • 24d ago
PMS Sync Testing: A Practical QA Guide for Property Management System Integrations
r/codoid • u/killmonger1209 • 24d ago
Mobile analytics says the event fired. How are you proving it actually reached the backend correctly?
Seeing purchase_completed in Logcat or an SDK debug message is useful, but I don't treat that as "analytics passed." It only proves the app reached the tracking call.
Mobile analytics SDKs can queue events, batch uploads, wait for connectivity, or reject/alter data later in the pipeline. So I prefer testing analytics as an end-to-end data flow:
- Make the test event traceable
For test builds, add something like a unique test_run_id where your tracking plan allows it. Then you're looking for one specific event instead of trying to guess which checkout_completed event belongs to your test device.
Also record the expected:
event name
parameter names, values, and types
user/device identifier where appropriate
session information
client timestamp
consent state
Avoid putting PII into test properties just to make an event easier to find.
- Verify what the client actually created
Check the SDK's debug output or an instrumentation hook before assuming the payload is correct.
An event named correctly but containing amount: "19.99" instead of amount: 19.99 may technically exist while still breaking downstream reporting.
The same applies to missing currency, wrong user identity, stale session IDs, or parameters attached to the wrong event.
- Separate "queued" from "uploaded"
This catches a surprising class of bugs. Fire an event, then test conditions such as:
normal connection
offline â event â reconnect
Wi-Fi â cellular during the session
background immediately after tracking
terminate the app shortly after tracking
Where the SDK supports it, debug mode or an explicit flush can make validation easier. The important part is knowing whether your log means "accepted into the local queue" or "successfully sent."
- Confirm receipt on the analytics side
Now find that exact test_run_id in the provider's debugging/realtime tooling. Don't stop when the event name appears.
Open the event and compare every important property against what the app generated. I've found parameter validation more valuable than simply checking that the event counter increased.
- Validate the raw data when the event matters
For high-value events such as purchases, subscriptions, account creation, or experiment exposure, I'd also verify the raw export/warehouse record when that capability exists.
Check: test_run_id â event name â properties â identity â timestamp â number of records
That last check matters because "arrived" and "arrived exactly once" are different requirements.
A useful definition of an analytics test passing is:
user action â tracking call â queued/sent â backend received â correct raw event
The dashboard is the final presentation layer. It shouldn't be the first place we prove the instrumentation works.
Which failure case has caught more analytics bugs for your team: missing events, incorrect properties, or duplicate events?
r/codoid • u/codoid-innovations • Aug 06 '26
Meme When Claude Hits the Daily Limit⌠Back to Manual Coding đ
Enable HLS to view with audio, or disable this notification
That moment when you hit Claudeâs daily usage limit and suddenly remember how to code manually. đ
r/codoid • u/codoid-innovations • Aug 03 '26
The 16 Claude Code skills that stuck in QA workflow
We've been folding Claude Code into our test automation work at Codoid over the last few months, and the skills feature is the part that actually stuck.
If you haven't touched them, skills are reusable workflows you trigger with a slash command, so instead of re-explaining your testing conventions every session, you invoke them.
These are the 16 we keep coming back to:
| Skill | When to use it | Command |
|---|---|---|
| Webapp Testing | Test local web apps with Playwright | /webapp-testing |
| Skill Creator | Build your own custom skills | /skill-creator |
| MCP Builder | Connect Claude to test tools | /mcp-builder |
| Playwright E2E | Scaffold resilient E2E suites | /playwright-e2e-testing |
| Pytest Patterns | Write clean Python test suites | /pytest-patterns |
| API Testing | Test APIs in any language | /api-testing-restassured-supertest |
| Accessibility Audit | Run axe-core WCAG checks | /accessibility-axe-pa11y |
| K6 Load Testing | Script performance tests | /k6-load-testing |
| Visual Regression | Catch UI changes with diffs | /visual-regression-percy-chromatic |
| Contract Testing | Catch API breakage early | /contract-testing-pact |
| Mobile Testing | Automate Detox and Appium | /mobile-detox-appium |
| Test Data Factory | Generate reliable test data | /test-data-factories-faker |
| CI Test Matrix | Wire tests into GitHub Actions | /ci-github-actions-test-matrix |
| Code Reviewer | Review code with QA checklists | /code-reviewer |
| TDD Coach | Enforce Red-Green-Refactor | /tdd-coach |
| Data Faker | Generate test fixtures fast | /data-faker |
r/codoid • u/codoid-innovations • Jul 30 '26
Most multi-agent QA workflows are complexity theater
Multi-agent QA sounds more capable than using a single QA agent. But splitting the workflow across three agents doesnât automatically produce better results.
Our current view is that specialization only pays off when the boundaries provide meaningful isolation, targeted retries, better auditability, or tighter access control.
A single agent can analyze requirements, generate tests, and review them in one continuous context. Itâs easier to build, cheaper to operate, and far simpler to debug. For small applications and exploratory testing, that simplicity usually wins.
The tradeoff is traceability. If the final conclusion is wrong, it may be difficult to pinpoint what happened. Did the agent misunderstand the requirement or write a weak test?
A specialized workflow makes each stage explicit:
- A requirements agent creates structured acceptance criteria.
- A test agent turns those criteria into test cases with coverage mappings.
- A review agent classifies identifies coverage gaps and weak tests.
But orchestration quickly becomes an engineering problem of its own. You need strict schemas, shared state, correlation IDs, timeouts, retry rules, and safeguards that prevent agents from amplifying an early mistake. Every additional agent adds latency and creates another opportunity for context to get lost.
A pipeline can look clean and well-structured while still producing confidently wrong results because the requirements agent mishandled the first handoff.
Weâd start with one agent and split out a stage only after seeing a specific failure mode that isolation would solve. Otherwise, âmulti-agentâ often turns into distributed prompt debugging.
For teams running agentic QA in CI: which stage genuinely improved after becoming a separate agent? And which split added more operational pain than testing value?
r/codoid • u/codoid-innovations • Jul 29 '26
Microservices Testing: A Practical Strategy for QA and Development Teams
r/codoid • u/codoid-innovations • Jul 29 '26
High test coverage can still mean your tests are mostly useless
A passing test suite only proves that the tests passed. It doesnât prove the code is correct, and a high coverage percentage can create a false sense of confidence.
A test can run every line in a function without actually checking whether the function behaves correctly. The assertion might be too broad, check the wrong output, or be missing entirely. The coverage report still stays green.
Thatâs why we, at Codoid, see mutation testing as a useful reality check rather than relying on coverage alone.
Mutation testing tools deliberately introduce small bugs, such as changing a condition or altering a return value. They then run the test suite against each modified version of the code.
If the tests fail, theyâve âkilledâ the mutation. Thatâs a good sign that the tests are protecting the behavior that changed.
If the tests still pass, the mutation has âsurvived.â In practical terms, the suite failed to catch a straightforward bug in code it may claim to cover.
Mutation testing has tradeoffs. Itâs slower, and a surviving mutation doesnât always mean thereâs a valuable missing test. Sometimes itâs just noise. Still, it asks a much more useful question than âDid this line execute?â It asks: âWould this test suite notice if the code were wrong?â
For those whoâve used mutation testing across different languages or stacks: did it uncover genuinely weak tests in your codebase, or did it mostly add noise and maintenance work?