Hacker News new | ask | show | jobs
by ditn 544 days ago
Generally these are only used in test methods, which is fine. I've never seen anyone use them outside that.
1 comments

What benefit do they provide in testing scenarios? I've never written Kotlin, but from an outsider's perspective, it seems like a slim benefit, outweighed by the cost of the mere existence of this syntactical oddity in the language's grammar.
When writing tests, you can name the methods more useful things, such as:

  class MyTestableClass {
    fun `methodName - when input does not parse to valid regex throw exception`() {

    }
  }
It's pretty clear what is under test in a situation like that. That's basically the only situation I ever see it used in (and would code-smell the heck out of it if I saw it in other circumstances).

People who are familiar with RSpec-style testing are very used to this sort of thing.

  describe MyTestableClass do
    context 'input parsing issues' do
      context 'when not valid regex' do
        it 'throws exception' do
          ...
        end
      end
    end
  end
Anecdotally, I've also found that such style naming for tests allows me to write out the desired names for all the tests ahead of time more easily and then implement them. That happens to be my flow.
methodName_whenInputDoesNotParseToValidRegexThrowException

They did a study and it isn't hard to read camelCase. https://ieeexplore.ieee.org/document/5090039

This study only compared camelCase to snake_case and what the results are mixed, depends on what you call "hard to read". They only seem to have tested finding identifiers from a word cloud, and it did take more time to read camelCase identifiers (although they were also resulted in more accuracy).

It's important to note that the researchers only tested short phrases with 2 and 3 words. "getNextPath" is a different beast compared to "methodName_whenInputDoesNotParseToValidRegexThrowException".

On the other hand, there is a good body of research that generally shows that proper sentences (not just 2-3 words) without spaces are harder to read, at least for English speakers[1]. Early medieval Latin manuscripts did not use space between words[2]. The fact that spaces were seen as an improvement when they were introduced, is probably telling.

[1] https://scholar.google.com/scholar?hl=en&as_sdt=0%2C5&q=unsp...

[2] Roman-era inscriptions did use an interpunct (a small middle dot) to separate words, but this practice fell out of fashion in Late Antiquity and Early Middle Ages and I'm not sure if it was ever the norm in handwriting.

From experience CI test reports are vastly more comprehensible at a glance.

That study compared camel case to underscore spaces. Well underscore space is still not as readable as methods with spaces and dashes.

Sure, but I like writing the other more. It's entirely a style thing and you're not required to do it :) it's also basically only ever seen in tests :)
I mean, it's harder to read compared to normal text with spaces and punctuation.
That doesn’t seem to be the case based on the study. And normal for one thing, such as paragraphs of prose, might not translate to another thing, such as a sequence of words in a line of code.
That’s just one study, and I’d argue we should write books in camel case to make them more compact if there’s truly no difference.
> That doesn’t seem to be the case based on the study.

The study does not say that camelCase is unequivocally as easy, or easier, to read.

Selecting the correct identifier from a list of 2-3 words (expandAliasTable, expandAliasTitle, etc.) is a wholly different exercise.

I like how tests are made in Python - you don't even need classes, just functions, and use a single assert keyword for everything. Also it's easy to parametrize them using decorators.
Parameterized tests in Junit are basically the same as decorators:

    @ParameterizedTest
    @ValueSource(strings = {"first", "second"})
    void fooGoesBar(String param) {
        ...
    }
Also, once you get used to assertj, you'll never want single-assert again. It's fantastically useful to know (for example) not just that two lists aren't equal, but specifically what elements differ.
> It's fantastically useful to know (for example) not just that two lists aren't equal, but specifically what elements differ.

Pytest shows the diff as well when using assert:

    >       assert y == x
    E       assert [1, 2, 3] == [1, 4, 3, 6]
    E         
    E          At index 1 diff: 2 != 4
    E         Right contains one more item: 6
    E         Use -v to get more diff
Great, what's the equivalent of this?

    assertThat(someCollection).map(Thing::getValue).containsExactlyInAnyOrder(3, 4, 5);
Parameterized tests are a huge, huge win, yeah. I am a big fan of them and look for how to do them in every test framework I use. RSpec was the weirdest for me; but NUnit and JUnit have been quite easy, and I'm not surprised at all they're easy in Python too (admittedly, I don't remember if I ever wrote them in that language).
In the RSpec case, those don't have to translate to method names with embedded spaces. It seems that using fun `...` instead of a dsl: test "..." is the mistake.
It's a place to put intetion that isn't so much of a second class citizen that it will likely be ignored and/or not updated if it ceases to be true. You want your test methods fine grained (many methods that each check one variation, instead of one method that checks a whole list of them) and every extra redundancy (method naming vs the variation of data actually passed vs documentation) increases the the chance of those redundancies getting out of sync.

In fact I've occasionally found myself writing reflection code to parse the test method name as input just to avoid that problem altogether (for name and data, not for documentation). And that was in plain Java even, the pattern could be far more useful with that kotlin naming freedom.

It reminds me of Spock tests written in Groovy. I have to help maintain a code base like that now at work where a Groovy zealot (who has moved on) convinced the teams to write tests in Groovy instead of Java.

When a test fails, the method name describes what it was supposed to do written out like a sentence enclosed in double quotes which seems like a win but not much of one.

When you need to add a new test or analyze if an existing test needs to be changed, you have to eyeball all the code in the test class because even with methods named with spaces, it's not always indicative of what it does.

With Java, I can sort a list of method names and have a better idea immediately what needs to be updated or added.

Spock is an exercise in syntax cleverness with regular confusion opportunity and little gain IMO. Way too much implicit syntax that IDEs struggle with.

Refactoring Spock tests sucks due to how the context is different based on the clause you’re in.

The test frameworks typically output the passing/failing function names. Adding spaces like this make them more human readable.

expectInternalServerErrorOnBadInput

Vs

expect internal server error on bad input

Isn't this breaking Jakob's law of the rest of the tooling though? I can se flows borking with something like "x failed at expect" in a majority of reporting tools not specifically meant to deal with this spaces in functions stuff.
Not really—-most CI reporting is based off junit/testng report XML files. I doubt your CI reporting is parsing out test names with regexes out of log files.
It’s better to quote a reserved word than to be unable to use it.
So that programmers have one more bikesheddibg reason, obviously.