PHPackages                             rtens/scrut - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. rtens/scrut

ActiveLibrary[Testing &amp; Quality](/categories/testing)

rtens/scrut
===========

Light-weight test runner for PHP

v1.2(10y ago)11.1k3MITPHPPHP &gt;=5.5

Since Jun 18Pushed 10y ago1 watchersCompare

[ Source](https://github.com/rtens/scrut)[ Packagist](https://packagist.org/packages/rtens/scrut)[ Docs](http://github.com/rtens/scrut)[ RSS](/packages/rtens-scrut/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (3)Dependencies (1)Versions (4)Used By (3)

Scrut [![Build Status](https://camo.githubusercontent.com/62d1c0e3aff30d2310f38e69df0b4793f087cfa0a31340576b3eb5c90cf15e57/68747470733a2f2f7472617669732d63692e6f72672f7274656e732f73637275742e706e673f6272616e63683d6d6173746572)](https://travis-ci.org/rtens/scrut)
======================================================================================================================================================================================================================================================================

[](#scrut-)

*scrut* is a full-fledged, light-weight xUnit-style test framework for PHP.

The Why
-------

[](#the-why)

Why write another test framekwork for PHP? One could easily argue that there are already [enough](http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#PHP), and one would be right.

But apart from the fact, that writing a test framework is great fun, the main reason that lead me to doing so was that [PhpUnit](http://phpunit.de/) started to feel kinda heavy, especially as a requirement of the micro-libraries in my [web application tool kit](http://github.com/watoki/), and the alternatives didn't convince me. Other minor reasons where that I needed a more flexible testing framework for experimenting with test styles and always wanted a framework that is aligned with my work flow.

Installation
------------

[](#installation)

To use *scrut* in your project, require it with [Composer](http://getcomposer.org/download/)

```
composer require "rtens/scrut"

```

If you would like to develop on *scrut*, clone it with [git](https://git-scm.com/), download its dependencies with [Composer](http://getcomposer.org/download/) and execute the specification with scrut itself (the bootstrapping is the major source of fun when writing test frameworks)

```
git clone https://github.com/rtens/scrut.git
cd scrut
composer install
vendor/bin/scrut

```

Usage
-----

[](#usage)

There are three ways to write tests with *scrut* which you can mix as you please.

### Minimalistic

[](#minimalistic)

The easiest and most minimalistic way to write a test, avoiding all dependencies on scrut, is to create a class in a folder (e.g. `spec`) like this:

```
class Foo {
    function thisOnePasses() {
        assert(true);
    }

    function thisOneFails() {
        assert(false, "Bang");
    }
}
```

Note that you don't need to follow any naming convention. *scrut* will execute all public methods of all classes it finds in the folder you point it to. You can use the `assert` function or throw `Exceptions` to make a test fail.

If you now run `vendor/bin/scrut spec` you should get the following output.

```
.F

---- Failed ----
Foo::thisOneFails [/home/derp/scrut/spec/Foo.php:9]
    Caught E_WARNING from /home/derp/scrut/spec/Foo.php:9
    assert(): Bang failed

=( 1 Passed, 1 Failed

```

The dot means that the first test passed, the `F` means that the second one failed and the reason is printed below followed by a summary of the test run.

### Integrated

[](#integrated)

A more integrated way is let the test class extend `StaticTestSuite` and use the `Assert` class to make assertions.

```
class Foo extends StaticTestSuite {
    function thisOnePasses() {
        $this->assert("1", 1);
    }

    function thisOneFails() {
        $this->assert->equals("1", 2);
    }

    function thisOneIsEmpty() {
    }
}
```

The output of `vendor/bin/scrut spec` should now be

```
.FI

---- Incomplete ----
Foo::thisOneIsEmpty [/home/rtens/testScrut/spec/Bar.php:12]
    No assertions made

---- Failed ----
Foo::thisOneFails [/home/rtens/testScrut/spec/Bar.php:9]
    '1' should equal 2

=( 1 Passed, 1 Incomplete, 1 Failed

```

Note that the empty test method results in the test being marked as "incomplete" because no assertions are made.

### Dynamic

[](#dynamic)

If you're not a fan of creating classes, then you might like the third way using dynamically created objects.

```
return (new GenericTestSuite("Foo"))
    ->test("foo", function (Assert $assert) {
        $assert("1", 1);
    });
    ->test("bar", function (Assert $assert) {
        $assert->equals(1+1, 2);
    });
```

which gets you

```
..

=D 2 Passed

```

Documentation
-------------

[](#documentation)

The documentation of *scrut* is written in the form of an executable specification. You find it in the [`spec`](http://github.com/rtens/scrut/tree/master/spec) folder.

Contribution
------------

[](#contribution)

I'm looking forward to any kind of contribution including feedback about how unnecessary this project is, bugs and suggestions for missing features. Just open a [new issue](https://github.com/rtens/mockster/issues/new) or check out the [open issues](https://github.com/rtens/mockster/issues).

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity16

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~143 days

Total

3

Last Release

3700d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/e687108526c164e4ad1c49b8228514541bd90d43ef70665a087d00e34a1f7559?d=identicon)[rtens](/maintainers/rtens)

---

Top Contributors

[![rtens](https://avatars.githubusercontent.com/u/1468866?v=4)](https://github.com/rtens "rtens (191 commits)")

---

Tags

testBDDTDDtest runner

### Embed Badge

![Health badge](/badges/rtens-scrut/health.svg)

```
[![Health](https://phpackages.com/badges/rtens-scrut/health.svg)](https://phpackages.com/packages/rtens-scrut)
```

###  Alternatives

[mockery/mockery

Mockery is a simple yet flexible PHP mock object framework

10.7k497.0M23.6k](/packages/mockery-mockery)[codeception/codeception

All-in-one PHP Testing Framework

4.9k86.2M2.9k](/packages/codeception-codeception)[orchestra/testbench

Laravel Testing Helper for Packages Development

2.2k39.1M32.1k](/packages/orchestra-testbench)[php-mock/php-mock

PHP-Mock can mock built-in PHP functions (e.g. time()). PHP-Mock relies on PHP's namespace fallback policy. No further extension is needed.

36918.1M98](/packages/php-mock-php-mock)[phpspec/phpspec

Specification-oriented BDD framework for PHP 7.1+

1.9k36.7M3.1k](/packages/phpspec-phpspec)[php-mock/php-mock-phpunit

Mock built-in PHP functions (e.g. time()) with PHPUnit. This package relies on PHP's namespace fallback policy. No further extension is needed.

1718.2M399](/packages/php-mock-php-mock-phpunit)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
