2 ms·
You mention the tools you can use to make it happen. I think we're at the point where you need concrete examples to talk about whether it's worth it or not. If
by tayo42 9mo ago
You mention the tools you can use to make it happen.
I think we're at the point where you need concrete examples to talk about whether it's worth it or not. If you have functions that can't be called twice, then you have no other option to test details in the implementation like that.
Yeah there's a tradeoff between torturing your code to make everything about it testable and enforce certain behavior or keeping it simpler.
I have worked in multiple code bases where every function call had asserts on how many times it was called and what the args were.
- shagie 9mo agoIn functions that you write, that might be possible. How would you assert that a given std::vector only was filtered by std::ranges::copy_if once? And how would you test that the code that was in the predicate for it wasn't duplicated? How would you write a failing test for this function keeping the constraint that you are working with std::vector? std::vector<int> doThing(const std::vector<int>& nums) { std::vector<int> tmp1; std::vector<int> tmp2; std::ranges::copy_if(data, std::back_inserter(tmp1), [](int n) { return n % 2 == 0; } ); std::ranges::copy_if(tmp1, std::back_inserter(tmp2), [](int n) { return n % 2 == 0; } ); return tmp2; }
- tayo42 9mo agoI know how I would do it in python. This is built into the stdlibs testing library, with mocks. Maybe dependency injection and function pointers for the copy if function. Then you can check the call counts in your tests. But idk the cpp eco system and what's available there to do it.
- shagie 9mo agoThe python code would be def some_call(): return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def print_evens(nums): for n in filter(lambda n: n % 2 == 0, nums): print(n) def func(): filtered = list(filter(lambda n: n % 2 == 0, some_call())) print_evens(filtered) if __name__ == "__main__": func() How would you write a failing test that prevents the list from some_call() from having the same filter applied to it twice?
- tayo42 9mo agoYou would use something like this https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.assert_called_once_with https://docs.python.org/3/library/unittest.mock.html#unittes... Then you would make the mock filter with patch and test the `func` function psuedo python code would be @patch(builtins.filter) def test_func_filter_calls(mock_filter): mock_filter.return_value = [2,4,6] func() mock_filter.assert_called_once_with([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
- shagie 9mo agoThat wouldn't fail though. It was called only once with [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]. The second time it was called with [2, 4, 6, 8, 10]. Likewise, if some_call returned [2, 4, 6, 8, 10] instead, it should only be called with [2, 4, 6, 8, 10] once then. However, the purpose of this test then becomes questionable. Why are you testing implementation details rather than observable? Is there anything that you could observe that depended on the filter being called once or twice with the same filter function?
- tayo42 9mo agoDid you try it? If it doesn't work there's also called once if you scroll up on the doc And as far as whether it's a good idea or not, I generally wouldn't, but was saying when it is important then you do have these tools available,llms aren't the first thing to check for these mistakes. It's up to the engineer to choose between trade offs for your scenario.
- shagie 9mo agoYes. The test passes. https://imgur.com/a/4qlTKlc https://imgur.com/a/4qlTKlc To try to monkey patch this in, you would need to also assert that it wasn't called with [2, 4, 6, 8, 10]. At which point, I would again ask "why are you testing that it _wasn't_ called with a given set of values?" The comment at the root of this is "Unit tests catch that kind of stuff". ... But unit tests aren't for testing internals of implementation but rather observable aspects of a function. Consider if the code was written so that it was def print_evens(nums): for n in nums: if n % 2 == 0: print(n) instead (with the filter being used in func()) This isn't something that unit tests can (or should) identify. It would come out in a code review that there is redundant functionality in func and print_evens. Using ChatGPT or another tool to assist in doing code reviews can be helpful (my original premise). https://chatgpt.com/share/697a64a6-33c0-8011-a0f8-ca4fec74ab1f https://chatgpt.com/share/697a64a6-33c0-8011-a0f8-ca4fec74ab... ChatGPT properly identifies the duplicated functionality (even though the code is using different idioms for doing the filtering for even numbers).