Plenty of "penetration tests" are a scanner run, exported to PDF, with a logo on the cover. They are cheap to produce, which is why they are common, and they are close to worthless because they answer the wrong question. A scanner tells you what might be a problem. A test tells you what an attacker can actually do.
If you are buying security testing, here is how to tell the difference before you pay rather than after.
Findings should chain, not just list
The interesting risk is rarely one dramatic vulnerability. It is three small things that combine. An endpoint that leaks a user identifier, plus an access check that trusts that identifier, plus an export function that does not re-check ownership, is a full customer database walking out of the door. Individually those look like low severity. Together they are the incident.
A scanner cannot see this, because chaining requires understanding what the application is for. Ask a prospective tester to describe a chain they found on a previous engagement. The answer separates people who test from people who scan, immediately.
Every finding needs a proof
A real report includes, for each finding, the request that triggered it and the response that came back. Not a severity score. Not a paragraph describing the class of vulnerability in general terms. The actual evidence, reproducible by your developer.
This matters practically as well as intellectually: a developer handed a proof of concept can fix the bug in an afternoon. A developer handed "possible IDOR, medium" spends the afternoon trying to work out whether it is even real. We have watched teams waste weeks re-litigating scanner output that nobody could confirm.
Access control is where the real bugs live
Broken access control has sat at the top of the OWASP Top 10 for years, and it is the first thing we test, because it is the most common serious flaw in applications built quickly. The test is unglamorous: create two accounts, then try to read and modify the first account's data while authenticated as the second.
Changing an identifier in a URL and getting someone else's record is the single most frequent serious finding we see. It requires no tooling, which is why a scanner will not find it and why it survives to production so often.
The report has to be readable by two audiences
The developer needs the request, the response, the fix. The owner needs to know what could have happened and what it would have cost. A report written only for engineers gets no budget allocated; a report written only for executives gets nothing fixed.
We write for both, and rank by real business exposure rather than by the scanner's default severity, because those two orderings are frequently different. A medium-severity finding on the endpoint holding all your customer data outranks a high-severity finding on a marketing page.
Insist on a retest
A test without a retest is half a service. You fix what was found, and then somebody has to confirm the fix actually closed it rather than moving it. Fixes that appear to work are common: input filtered on one path and not another, an access check added to the read endpoint but not the write one.
Retesting the specific findings should be included, not billed as a second engagement.
The one thing to tell your tester
Scope it honestly and tell them what worries you. A tester who knows the admin panel is the crown jewel will spend their time there. A tester given a URL and no context spends the first day working out what the application does, which is your budget being spent on discovery you could have provided in ten minutes.
And ask for critical findings to be reported immediately rather than at the end. If something serious is open right now, you want to know today, not in the final report next week. That is how we run application testing, and it is a reasonable thing to require of anyone you hire.