Conversation
| // Was not able to find more reliable solution to capture logcat per test. | ||
| val startedTest: Pair<String, String>? = newline.parseTestClassAndName("TestRunner: started: ") | ||
| val finishedTest: Pair<String, String>? = newline.parseTestClassAndName("TestRunner: finished: ") | ||
| val startedTest: Pair<String, String>? = newline.parseTestClassAndName("""(.*TestRunner.*: started: )(.*)\((.*)\)""".toRegex()) |
There was a problem hiding this comment.
Any chance to solve it without Regex?
My main concern is performance and readability :)
There was a problem hiding this comment.
I wondered about perf, but personally find it very readable. It's easy to see the capture groups and destructuring makes it clear exactly what were pulling out of the log line.
I can give a non-regex implementation a shot too.
There was a problem hiding this comment.
If it's not hard, please try, would love to compare!
There was a problem hiding this comment.
Yeah, I'd compare it with non-regex solution, too
There was a problem hiding this comment.
How about:
fun String.parseTestClassAndName(): Pair<String, String>? {
val tokens = split(':')
if (tokens.size != 3) return null
if (tokens[0].trimStart('I', '/').startsWith("TestRunner")) {
if (tokens[1] == " started" || tokens[1] == " finished") {
return tokens[2].substringAfter("(").removeSuffix(")") to tokens[2].substringBefore("(").trim()
}
}
return null
}I'm not sure about the performance of split(). Since it's a single character I'm assuming it's O(n) where n is the length of the string.
There was a problem hiding this comment.
Maybe the first check should be
if (!trimStart('I', '/').startsWith("TestRunner"))so we can avoid O(n) on every log.
fun String.parseTestClassAndName(): Pair<String, String>? {
if (!trimStart('I', '/').startsWith("TestRunner")) return null
val tokens = split(':')
if (tokens.size != 3) return null
if (tokens[1] == " started" || tokens[1] == " finished") {
return tokens[2].substringAfter("(").removeSuffix(")") to tokens[2].substringBefore("(").trim()
}
return null
}| else -> it.substringAfter("(").removeSuffix(")") to it.substringBefore("(") | ||
| } | ||
| fun String.parseTestClassAndName(regex: Regex): Pair<String, String>? { | ||
| return regex.find(this)?.destructured?.let { (_, testMethod, testClass) -> Pair(testMethod, testClass) } |
There was a problem hiding this comment.
Hm, typically to improve performance you create Pattern by Pattern.compile("…") once and use that
|
Btw, looks like you're committing with wrong git config, your commit doesn't have your avatar You can check if commit email matches expected that is attached to github account: git logAnd if it's not, fix it like that: git config user.email "correct@email.com"
git commit -a --amend --reset-author |
|
Ah, also please add test case(s) that show how old parsing failed and new one fixes that problem! Thanks :) |
|
@artem-zinnatullin Please have another look. I optimized and added some tests. |
| } | ||
|
|
||
| private fun saveLogcat(adbDevice: AdbDevice, logsDir: File): Observable<Pair<String, String>> = Observable | ||
| class LogLineParser { |
There was a problem hiding this comment.
You don't need class :)
As you can see, Composer is class-less other than data-classes, just drop a private top-level function :)
There was a problem hiding this comment.
I can't test it if it's private.
|
|
||
| context("parse test class and name") { | ||
|
|
||
| it("parses old TestRunner start logs") { |
There was a problem hiding this comment.
Maybe give better name? "old" doesn't really explain what is old and what is new
Also, you can extract subject under test which is a log line that you parse into a separate variable for better test structure
| val tokens = logLine.split(':') | ||
| if (tokens.size != 3) return null | ||
|
|
||
| if (tokens[1] == " started" || tokens[1] == " finished") { |
There was a problem hiding this comment.
this looks vulnerable to spaces, maybe trim?
|
|
||
| private fun saveLogcat(adbDevice: AdbDevice, logsDir: File): Observable<Pair<String, String>> = Observable | ||
| class LogLineParser { | ||
| fun parseTestClassAndName(logLine: String): Pair<String, String>? { |
There was a problem hiding this comment.
I honestly like this non-regexp version better, much more understandable!
There was a problem hiding this comment.
I have a bug, I forgot the "newer" logs have a ton of stuff before "TestRunner". I'll submit an update later.
There was a problem hiding this comment.
Sure, so far it looks really good, keep it up 👍
|
bump |
artem-zinnatullin
left a comment
There was a problem hiding this comment.
Awesome work!
| } | ||
|
|
||
| it("extracts test class and method") { | ||
| assertThat(args).isEqualTo(Pair("com.example.SampleClass", "someTestMethod")) |
There was a problem hiding this comment.
nit: you can use infix function to create pair, it'll be little bit shorter
"com.example.SampleClass" to "someTestMethod"| import org.jetbrains.spek.api.dsl.context | ||
| import org.jetbrains.spek.api.dsl.it | ||
|
|
||
| class LogLineParserSpec : Spek({ |
|
Just in case, I believe when GitHub will "Squash and Merge" it'll use first commit as base and might not associate it with your GitHub account, but I'm not sure Possible solution: rebase with |
ce4d929 to
389e31b
Compare
|
Fixed. Thanks @artem-zinnatullin |
|
@yunikkk can you PTAL and merge? :) |
|
Please, merge!) |
|
@evgengal I just built a jar and deployed that so I wouldn't have to wait. Put a fix for screenshots not working in there too, but it's kind of a special case. |
|
@christopherperry merged and released 0.3.3 with it, thanks! |
|
Well...now it doesn't work on emulators...
|
|
I just created a new issue for what @CristianGM is commenting, in case you'd like to treat it as a different issue: #151 |
|
@CristianGM @Sloy thanks for reporting, adding fix. |
Fix for #129
Might need more testing.