Today I’m talking about something a little broader than usual. I’ve started trying to get comfortable with Pester, which is a framework for writing tests in PowerShell. The first thing I’ve figured out with Pester is that I’m really not writing well formed scripts. They’re super hard to test because they aren’t really broken out into distinct elements.
This prompted me to refactor about all of my core scripts, an unpleasant but important process. One of the things that has occurred to me is that I, up until now, have been using modules as a bit of a last resort. I try not to write them if I don’t have to and I often just load functions into an existing catch all tools module. I just didn’t like putting in the effort to write a module, you need to remember where you stored it and remember to call it in your script*.
So now looking at the way I bundle my scripts I’ve decided that I like module files. I can store Variables and functions that are used in my script but never exposed to it. I can keep my functions bundled together, and I can nest other modules. It’s pretty handy. It also keeps my actual scripts really short and makes it easier to add functionality. I can add a new function to a module or just switch the way I use my existing functions.
My job is largely writing new monitors for large enterprise applications in PowerShell. I’ve now taken to having every single monitor script call it’s own module. A monitors gets stored in it’s own folder with at least a monitor script and a module file. I also add other scripts that support the monitor in there as well. Like, my tests file so I can validate my monitor after I change it and the configuration data for the Scheduled job that runs it. It took me a bit to get used to it but I’ve now started writing a lot of modules files and using them in a lot of my scripts. Anything that can be used for multiple scripts is stuffed into a core module, everything else goes into a script specific module.
I was always hesitant to add external dependencies to my scripts, I worried about breaking something unintentionally. Well it turns out if you aren’t writing tests for your scripts you are constantly at risk of having them break. The worst part is if you aren’t testing on a regular basis your only way of knowing a script is broken is when you’re confronted with the results of a failure. I’ve added external dependancies but I also added tests to provide me absolute certainty that my production scripts are doing what they’re supposed to do. I feel a lot more confident about my monitors and scripts now than I did before, because when one of them stops doing what it’s supposed to do I know right away. Production environments can sometimes change on the fly and it’s pretty easy to have a script stop working because someone changed the way an App works. With good tests you’ll notice something isn’t right well before anyone else does, and that feels really nice. And with well modularized scripts it’s really easy to adapt to changing circumstances.
Ok so that’s all I have for today, I’d really love feedback on this. How do you feel about modules? Do you already test your scripts? Is this idea interesting to you or does it sound odd in some way?
Thanks a lot for taking the time to read this!
*this only applies if it’s not in your PSModulePath and/or you’re in Powershell V2 or below