-
-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Snapshot testing #393
base: master
Are you sure you want to change the base?
Snapshot testing #393
Conversation
c29aa2c
to
ef3a711
Compare
I really like this idea. It's about year and half I created something similar in my local repo. But as a Tester's plugin and on high layer that this. Actually, I didn't hear about snapshot testing till today. So thanks :) To issues you mentioned... It's quite long in my mind that the Tester could support "user's arguments" from CLI. Some UNIX tools (based on The I have to think about the rest. But definitely 👍 |
👍 that would greatly improve extensibility. It's basically the only reason why snapshot testing can't be made as an external plugin without resorting to env variables.
I believe Looking forward to what you have to say to the other points! |
Failure can be distingushed by triggered error. |
Thinking about API, just for discussion. Not sure, there should be class Signature of method could be Assert::snapshot('name', $foo);
Assert::snapshot('name', $bar); What do you think? |
c293e8d
to
f5d9644
Compare
@milo that was something I was considering too. I've tried the suggested approach and it looks really good. Does anybody have any idea why the test fails on appveyor? |
eaaeb7b
to
7184606
Compare
ee525b7
to
6ca248e
Compare
Try to have path to phps file shorther then 255 chars. |
f5d9644
to
a46d1e4
Compare
This one is 88 characters long. I've even made it use platform-specific directory separator, but it doesn't seem to help. Unfortunately I don't have any experience with appveyor and not much with Windows either, so it's a mystery to me 😟 |
37f5151
to
c3bd1b2
Compare
4ae29b9
to
0899819
Compare
Ha, I've accidentally found why appveyor failed. It's not a feature, it's a bug, apparently not fixed until PHP 7.2.18 via this commit. I'm now skipping the test in environments where this bug is manifested and everything is finally green 🍏 |
a2312d9
to
84506f2
Compare
0df3c7e
to
062041b
Compare
3267365
to
9d28a53
Compare
dddb52b
to
78555c7
Compare
95674fc
to
c5eff68
Compare
cc8395d
to
8b22550
Compare
2fee261
to
c118637
Compare
Snapshot testing is a technique which allows users to instruct the testing framework to generate and store a snapshot of a tested value and in the subsequent runs assert that the value matches the snapshot. It presumably gained popularity among web developers because it was introduced in Jest to facilitate testing of the user interface. On backend, it is particularly useful e.g. for testing API responses.
I'd like to explain in short some of the design decisions – first and foremost, why this can't be done in an external code similarly to PHPUnit plugins: Tester runs tests differently. Where
in_array('--update', $argv)
is sufficient in PHPUnit and works even in third-party code, Tester requires changes in the test runner to pass the information to the child processes.I added the
--update-snapshots
flag and an environment variable. In the updating mode, tests with new or updated snapshots fail. I initially skipped them, but then I changed my mind: PHPUnit plugins mark such tests as incomplete, which is a PHPUnit-specific concept and is somewhat different from skipped tests. I think that in Tester, failing the test is semantically more correct than skipping.As for the assertion API, I started with a simple
Assert::matchSnapshot()
method, but the code eventually grew with the reading and updating logic, so it started to make sense to extract it to a separate class:Snapshot
. I am considering adding the method back toAssert
as an alias so that theAssert
class remains to be the primary public API, but I don't have a strong opinion on this.The
Snapshot::match()
method requires a snapshot name. I played with generating it from test arguments, but I couldn't figure out a way to make it deterministic in all cases, especially accounting for the fact that@testCase
s can be executed as a single test as well as each method in a separate job. In the end it was much easier to leave it to the developer. The only problem is that the snapshot name is used as a part of the snapshot file name, so I guess it should be validated against a limited set of characters – or at least it should be well documented that it has to be a safe string. What do you think?The last thing to point out is that
var_export
andeval
are used for storing and reading the snapshot value. I tried other solutions such as JSON or serialize and whilevar_export
also has its trade-offs, it still seems to be the best one: it doesn't changex.0
floats tox
integers like JSON does; it produces PHP code and as such is instantly readable, as opposed toserialize
d values. Thevar_export
function is bad at serializing objects, but objects do not typically need to be stored in snapshots. I guess that as long as this limitation is documented, it should be good enough. It's also what the aforementioned PHPUnit plugins use.