Update wiki on testing operations #7
-
I'm curious as to what the recommended approach is on testing operations? We've started using them and it's a good concept, but I'm uncertain whether these are to be tested as unit or functional as I referred to the wiki on testing jobs and features. Currently one of my operations relies on a DTO passed through to it that has been processed in previous jobs. If I was to functionally test it, I will need to either manually set all the attributes of the DTO, or run the jobs within the test to prepare the object. But I'm not too keen on doing the latter. |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments
-
I think I want to upvote this one since its always good to have examples of writing tests in the documentation. |
Beta Was this translation helpful? Give feedback.
-
@lezhnev74 I second that |
Beta Was this translation helpful? Give feedback.
-
agree to this. hope we could have a sample CRUD testing How do you test all jobs and features in 1 single command? |
Beta Was this translation helpful? Give feedback.
-
I doubt lucid itself warrants some special conventions or gotchas in terms of testing. It's a general purpose question. Personally, I usually don't think of a unit testing in context of isolation because from my experience it hurts the quality of your tests. You start mocking dependencies because you set out to write a "unit" test and soon enough your test suite becomes a glorified spell checker. It's also hard to do TDD in this way because mocking breaks a simple arrange->act->assert logic that makes it click. If we were to follow a classic Laravel distinction between Feature and Unit tests (talking about default test folders) it's simpler to think of it in the following way. Feature tests are responsible for testing your http endpoint, console command, etc. from start to finish. Unit tests are responsible for lower level functionality, but does not necessarily imply testing a single class in isolation. From that perspective operation test is kinda always a unit test, although not it the way you expect. This might sound bizarre but it will make more sense why I put it this way once we get to the end of this explanation. So to answer the original question, you will need to actually build a DTO if you were to test your operation properly. However, you should use factories for constructing test objects rather than running a job within an operation test. Otherwise, that job will change soon enough breaking a whole bunch of unrelated tests. Now, if we were to avoid mocking facilities that rely on your DTO and always test the real thing it begs the question how to avoid repeating yourself. You don't want your feature and operation/jobs tests to repeat the same checks over and over again. The answer is very simple. You don't need to test every single class. Test what your application does, not how it does it. As a rule of thumb, always start testing from the highest abstraction level (i.e. controller action or feature in lucid). Ask yourself a question: can I test this logic in its entirety with feature test? If so, just write a feature test and be done with it, you can skip testing operations/jobs. If it's a complex feature that involves multiple conditions, third-party API calls etc. THAN you might want to drill down to a lower level. For example, you may write a separate test for operation that calls a third-party API and mock this operation in your feature test. But other operations and job might not warrant their own test. Anyway, what I'm trying to say is that unit testing involves contextual thought process. If you indiscriminately test every single class I can gurantee that most of your tests are useless and probably riddled with mocks. Codebases like this are fragile because you need to rewrite tests every time you change original code. This kinda defeats the purpose of testing because the whole reason we write them is to make refactoring easy and protect us from accidental changes. TDLR: prefer functional testing to testing in isolation, start writing tests from a controller action and drill down to testing lower levels like operations and jobs ONLY when situation calls for it, have factories for using DTOs in tests, avoid indiscriminate mocking and having tests for one job/operation rely on another job/operation. |
Beta Was this translation helpful? Give feedback.
-
In addition to the splendid answer by @adiachenko I would like to point out that a humble example of testing has now been covered in the new docs at https://docs.lucidarch.dev/operations#testing |
Beta Was this translation helpful? Give feedback.
I doubt lucid itself warrants some special conventions or gotchas in terms of testing. It's a general purpose question.
Personally, I usually don't think of a unit testing in context of isolation because from my experience it hurts the quality of your tests. You start mocking dependencies because you set out to write a "unit" test and soon enough your test suite becomes a glorified spell checker. It's also hard to do TDD in this way because mocking breaks a simple arrange->act->assert logic that makes it click.
If we were to follow a classic Laravel distinction between Feature and Unit tests (talking about default test folders) it's simpler to think of it in the following way. Feature tes…