How can I disable Fabric: Crashlytics and Answer when running tests?
Is there any other way to disable Crashlytics during the test instead of putting this code before every test?
@LargeTest
@RunWith(AndroidJUnit4::class)
class AcceptanceTest {
@Before
fun setUp() {
val crashlyticsKit = Crashlytics.Builder()
.core(CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build())
.build()
Fabric.with(InstrumentationRegistry.getContext(), crashlyticsKit)
}
}
and avoiding to put a global boolean like IS_TEST_MODE
I find a better and cleaner way to disable and manage Fabric.
In my application I use slf4j-api
, a log API used a lot in web development. With this API you can create appender, so I decided to create a Fabric Appender and use this appender only when the app run.
slf4j
with Logback
build.gradle
dependencies {
...
// Log
compile 'com.github.tony19:logback-android-core:1.1.1-6'
compile 'com.github.tony19:logback-android-classic:1.1.1-6'
compile 'org.slf4j:slf4j-api:1.7.21'
}
src/main/assets/logback.xml
<configuration>
<appender name="FABRIC" class="path/to/your/FabricAppender" />
<appender name="LOGCAT" class="ch.qos.logback.classic.android.LogcatAppender">
<tagEncoder>
<pattern>%logger{0}</pattern>
</tagEncoder>
<encoder>
<pattern>[PUP] %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="LOGCAT" />
<appender-ref ref="FABRIC" />
</root>
By default Logback
has a customize appender working with Logback
. You can comment the FABRIC
part we will be explain later.
src/androidTest/assets/logback.xml
<configuration>
<appender name="LOGCAT" class="ch.qos.logback.classic.android.LogcatAppender">
<tagEncoder>
<pattern>%logger{0}</pattern>
</tagEncoder>
<encoder>
<pattern>[PUP] %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="LOGCAT" />
</root>
</configuration>
You don't want to have Fabric appender here! because you want your instrumented test running only with Logcat
Logback
Now you can easily log using the powerful API of slf4j
like below
class MainActivity : AppCompatActivity() {
private val log = LoggerFactory.getLogger(javaClass)!! // Call your logger in each class with this line
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
log.info("Activity start")
// ...
} }
Logback
FabricAppender.kt
package your.package.log
import android.content.Context
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.spi.ILoggingEvent
import ch.qos.logback.classic.spi.ThrowableProxy
import ch.qos.logback.core.UnsynchronizedAppenderBase
import com.crashlytics.android.Crashlytics
import com.crashlytics.android.answers.Answers
import com.crashlytics.android.answers.CustomEvent
import io.fabric.sdk.android.Fabric
class FabricAppender : UnsynchronizedAppenderBase<ILoggingEvent>() {
companion object {
private var isFabricInit = false
fun init(context: Context) {
Fabric.with(context, Crashlytics(), Answers())
isFabricInit = true
}
}
override fun append(event: ILoggingEvent) {
if (isFabricInit.not()) return
when (event.level.levelInt) {
Level.ERROR_INT -> {
val throwable = (event.throwableProxy as ThrowableProxy).throwable
if (throwable != null) {
Crashlytics.logException(throwable)
} else {
Crashlytics.log(event.message.replace(": {}", ""))
}
}
}
}
}
This appender will send exception to Crashlytics
every time you call log.error("Something wrong happen!!")
. As you can see, you can fully customized the appender.
class MainActivity : AppCompatActivity() {
private val log = LoggerFactory.getLogger(javaClass)!! // Call your logger in each class with this line
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
FabricAppender.init(this) // Init before the first log
log.info("Activity start")
// ...
} }
Now your fabric will be totally isolated to your code by using the slf4j
API, and will be not use during your instrumented test yataaa!!! You can find other appender on internet (send to ELK, file, etc.)