The Frustrations of TDD, Composer, Laravel, and Package Development
Tags: laravel, php, tdd, composer
Published: 2019-02-23 05:31:12

---
title: The Frustrations of TDD, Composer, Laravel, and Package Development
published: true
description: Not as ranty as you might expect. Practicing being the most constrained is difficult.
tags: laravel, php, tdd, composer
---

(I'm pretty sure Twitter exploded.)

Over the last couple of weeks, I think - kinda lost track of time - I've been posting somewhat daily threads describing the adventures of redeveloping the 8fold platform, affectionately called AMOS, which I will refer to as just Amos from here on out.

Not gonna bother too much with recaps, take a look at the thread, if you're curious.

Today was kind of the final straw for me with trying to do things the way I thought would be most beneficial and complied with my desire to constrain myself as strictly as I could to various principles:

1. TDD in general, with a fair refactoring Javier Trevino Saldana, as I can't [notice any nuance lost](http://bit.ly/2E6ILXQ).
2. Leverage what you have until you can't.
3. Packages should be independently testable, even in a monorepo.

That last one is kind of where I broke today, which rippled a bit across the others.

Composer is to PHP what NPM is to JavaScript. The `vendor` directory is equivalent to the `node_modules` folder. Composer offers something called autoloading. Which helps PHP find what your application is looking for by way of voodoo I have not dove into beyond the fact it has to do with an `autoload.php` file it stores *inside* that vendor folder. That's important because the references are relative to *where* the composer file is when you run `$ composer dumpautoload`.

My monorepo structure looks something like this:

```
/8fold
    /AMOS
    /CoreCharon
    /AppIdeasmith
    /Laravel
    /vendor
    composer.json
    phpunit.xml
```

The first three folders are technically packages, Laravel services, to be injected into the service container later. The `Laravel` folder holds [Laravel](https://laravel.com). The vendor folder is where all the installed packages go. The `composer.json` file is similar to `package.json` file for node. The `phpunit.xml` file is the configuration for PHPUnit, which is the de facto testing package for PHP (see, PHP does have nice things).

Here's where it gets interesting.

```
/8fold
    /AMOS
        composer.json
        phpunit.xml
    /CoreCharon
        composer.json
        phpunit.xml
    /AppIdeasmith
        composer.json
        phpunit.xml
    /Laravel
        composer.json
        phpunit.xml
    /vendor
    composer.json
    phpunit.xml
```

Putting a vendor folder along with composer and phpunit files at root I thought was a good move. Because each package can have its own vendor folder as well, I didn't want them to though; so, I used symlinked folders to point to the root one.

Things were going pretty good. Tests were working. Didn't have to hop from folder to folder in Terminal. The only annoying part was I'd have to go into the app I was testing and run `composer dumpautoload` every once in a while. I hadn't hit a unit test yet that needed a database table created yet; so, yeah, feeling pretty good about myself. 

Of course, I should know better than to put that into the universe.

After three hours of trying to come to and elegant solution I relented and decided to create a database table. In my defense, I held to my constraints:

4. The relational database should be for storing relationships (obvious) and no user-generated or -focused content.

Basically, the table has a single field at the moment: username. I created the migration. I ran the tests. 

They exploded all over the screen like when I used to die playing Doom II as a kid.

![Final credit of Doom II by Id Software](https://thepracticaldev.s3.amazonaws.com/i/2uq3dmlsnv8etsg8qup2.PNG)

Frustrated and having spent about as much time as I wanted to in trying to test the packages in isolation using a package called Testbench, which is the only one I can find specifically for testing packages *for* Laravel *outside* Laravel, I decided to put the keyboard down and start weighing pros and cons of what I figured would need to happen.

1. Pull testing back into Larvel-proper. This would take the tests away from the context of the packages they were testing. This would also give me a single place to run all terminal commands related to the project. (Hmmmm...symlinks?)
2. No, that was pretty much it...

So, I started doing just that. I didn't do it all at once because I still need to make progress on this project beyond futzing around with the internals. I moved a test, making sure it needed the database and the new table, with one field. Tests past. I kept moving things. I kept building things.

An hour later, I felt I was making progress.

TDD was demonstrating why the debates around what it's good for are. Is it design or validation? I lean toward design as I was quickly able to start refactoring, even building a new class with more control over its destiny than the previous iterations.

I learned *way* more about Composer than I ever would have otherwise.

Learned quite a bit more about Laravel as well. Mainly, for me, at this point, I'm more interested in using the well designed and developed classes in isolation than I am necessarily interested in using the framework as a whole.

Package Development became much more interesting when I got the [free course preview from Marcel on creating local packages](https://phppackagedevelopment.com/#newsletter-signup), granted it's also one of the videos you get to see when you go into the lessons. Basically, I finally understood how to get Composer to treat my computer like it was Packagist, which is like NPM for JavaScript.

That's it. Hope that wasn't too filled with hatred and anger. :)