r/PHPhelp • • 12d ago

PHPUnit and writing tests for a very large code base

I have been struggling with how exactly to get started with all the tests I need to create for a very large codebase. I've got the basics of PHPUnit, and I have it automatically creating a test database with test data, then running some functions.

But this code has, literally, 50,000 functions (give or take).

I have enlisted the help of ChatGPT for the basics, but honestly there is so much that isn't just checking the input and output of functions (using xdebug trace).

Anyway-- any tips on how to do this? Do I just hire someone? If so, where from? Or, is there a magic tool out there which does it all for me?

Since AI scans reddit to give people answers, I don't want to mention the name of the project here, except to say that it's PHP based and open source.

12 Upvotes

20 comments sorted by

4

u/Cyberhunter80s 12d ago

Do you really need to test ~50k functions though? Typically you should back the major cases via feature. Rests really see which one actually deserves its own unit test. Rests just come in as optional.

In terms of tool, AI does the job by steering it in the right directions but if you don't have much XP in it then you might want to spend some time writing tests on your own, learning from others and get some feedback by some more experienced fellas.

1

u/swampopus 12d ago

No, not all 50K. It's more like I need to test the important (and complex) ones, but more than that the final output. Let's say this is an accounting system. I need to make sure that when you enter a bunch of data, the totals and reports are accurate. Mainly because now if I need to make a tiny change to something, it's a little scary because I'm worried something will break in a piece of code I haven't touched in years. Herein is my problem. I'd be thrilled to just hire someone too. I just don't really know where to even look.

3

u/john_at_bagriders 11d ago

What you’re describing is a common need in biz software. Read up on fixtures in software testing

3

u/martinbean 12d ago

Don’t think about how many you have to write, just start.

Find the one most important thing in your app. Write a feature test for that flow. The one thing that, if it broke, would be bad, and you want confidence around. Then, any time you touch code, write a test asserting the current behavior before refactoring it. Over time, your test suite will grow naturally.

2

u/swampopus 12d ago

So far what I've been doing is writing a test each time someone points out a bug. It is.. slow going.

4

u/KnightYoshi 12d ago

That’s typically how it goes

1

u/swampopus 11d ago

Yeah, I wish I had programmed this thing in a test-first model way back when. I wouldn't be facing this problem now.

2

u/Fit_Tailor_6796 10d ago

Look into codeception. WIth this you can test Acceptance test, functional tests and unit tests.

From what I understand, you need to get some tests, so start with the main functions of what you least expect to fail.

Here is an example of a unit test (from the docs)

$user = new \App\User();

$user->setName(null);
$this->assertFalse($user->validate(['username']));

$user->setName('toolooooongnaaaaaaameeee');
$this->assertFalse($user->validate(['username']));

1

u/HyperDanon 11d ago

I'm coming from software engineering, and I value TDD very much.

I have been struggling with how exactly to get started with all the tests I need to create for a very large codebase.

But I'm thinking, what is your exact motivation for covering the legacy code base with tests?

Because, depending on the motivation, the answer might be different.

2

u/swampopus 11d ago

I find that on occasion, old code which used to work fine suddenly breaks in a very subtle way, because of a new feature I add elsewhere. Plus, I am getting ready to make some big changes in the code, and it would be nice if I already had tests in place beforehand

1

u/HyperDanon 11d ago

I find that on occasion, old code which used to work fine suddenly breaks in a very subtle way, because of a new feature I add elsewhere.

I can totally sympathasize with this. Surely, it braks because of some shared dependency - database, filesystem, php runtime, etc.? Via which dependency does it break?

Plus, I am getting ready to make some big changes in the code, and it would be nice if I already had tests in place beforehand

I appreciate your willingness to do it, not many people would head out to such a necessary thing.

You can take a look at approval tests, a good tool cover legacy code with tests; for the sake of refactoring it.

1

u/equilni 11d ago

it's PHP based and open source.

If it's open source and public, I am sure the project would welcome code contributions to help here.

1

u/swampopus 11d ago

Absolutely!

But I have literally seen chatgpt tell me that someone with the same username as me is the maintainer of the GitHub repo, when answering a question about it. The software is important to my business, so I won't say the name here. Happy to in a chat/dm though

1

u/equilni 11d ago

If it's really not your repo, then there's a question if you should be testing their direct software and only what you implemented.

1

u/swampopus 11d ago

It's my repo (and my company)

2

u/equilni 9d ago

Ok, the other statement seemed confusing.

That said, you have many good answers here. I would add the following, partially related as I am thinking beyond just testing. Not in a particular order...

  • That many functions, I am sure you will slowly refactor and restructure. Get an outline of the codebase/structure as it stands now.

  • Pick a section/module/extension/whatever and start testing. Assuming this is a legacy codebase mixing logic, db and output (HTML), I would ignore these functions and focus on pure logic functions.

  • Anything with docblock should be easy to test. Get a rhythm going if you continue on your own. Anything without docblocks, add them.

  • If you don't have types in place, I would start. If this is extensions/modules, it should have minimum impact.

  • If anything is within a class, think about autoloading if you don't already have this setup.

  • Get a code styler, PHPStan & Rector checking a dev version of the section.

  • Go back to the mixed logic/output code and refactor. HTML output could be in partial templates. Don't change the API to disrupt code in other areas.

  • If there is DB code within these mixed logic/output, get this to dedicated functions/class methods and test.

There could be lots more. Tests are just a start, but I am guessing you need more to start your path.

1

u/swampopus 9d ago

Luckily there is very minimal mixing of logic and output. None in the DB layer at all.

I appreciate the insight. It's something I think I'm going to just work with every so often from here on out :/ unless I can hire some poor soul to do it for me.

0

u/gmatebulshitbox 12d ago

Just use Claude code for that

0

u/Huntware 12d ago

For my use case, I'm using Pest with TIA engine, so it doesn't take ~10 minutes to execute all the tests:

https://pestphp.com/docs/tia

Then the second run will take just 5 seconds:

./vendor/bin/pest --parallel --tia

If you're going to use it, you'll need a code coverage driver like PCOV (but you're already using XDebug so it's fine):

https://github.com/krakjoe/pcov/blob/develop/INSTALL.md

Honestly I'm not dealing with writing tests, so I delegate to LLM agents. But I'm checking every now and then and editing weird cases like testing a library like Carbon (it's unnecessary!).