diff --git a/app/build.gradle b/app/build.gradle index 1d95671..8c0b1c0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -108,6 +108,8 @@ dependencies { testImplementation 'org.mockito:mockito-core:3.12.4' androidTestImplementation 'org.mockito:mockito-android:3.12.4' androidTestImplementation 'org.mockito:mockito-inline:3.12.4' + androidTestImplementation 'org.mockito:mockito-android:3.12.4' + testImplementation "androidx.arch.core:core-testing:2.2.0" testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.1' diff --git a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt index eb39e71..5de50a6 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt @@ -25,12 +25,10 @@ import com.example.hpostesting.presentation.utils.MyDialogListener import com.example.hpostesting.presentation.utils.UIUtils import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.ktx.Firebase -import com.google.firebase.perf.ktx.performance import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding import kotlin.math.abs import kotlin.math.log10 -import kotlin.math.round @Suppress("MemberVisibilityCanBePrivate") class HemoCubeFragment : Fragment() { @@ -44,7 +42,6 @@ class HemoCubeFragment : Fragment() { private var resultData: String = "" private var currentResultData: String = "" private var isUsingExistingBuffer = false - private var loginId: String = "" private var isTestOngoing = false private var startListening = MutableLiveData(false) private var led1BufferForDevice = 0.0 @@ -59,7 +56,7 @@ class HemoCubeFragment : Fragment() { private var fittedAbs2 = 0.0 private var fittedAbs3 = 0.0 private var fittedAbs4 = 0.0 - private var _predictedDenovixRatio = 0.0 + private var calculatedPredictedDenovixRatio = 0.0 private var validationError = false private var deviceHardwareId = "" private var allErrorMessages = "" @@ -211,9 +208,9 @@ class HemoCubeFragment : Fragment() { apply { DataHolder.hemoCubeTestData?.let { currentDeviceData?.coefficients?.let { coefficients -> - val coefficient1 = coefficients[0] - val coefficient2 = coefficients[1] - val result = coefficient1 * coefficient2 +// val coefficient1 = coefficients[0] +// val coefficient2 = coefficients[1] +// val result = coefficient1 * coefficient2 } } isOnline = isNetworkAvailable @@ -394,7 +391,7 @@ class HemoCubeFragment : Fragment() { } } - resultData.contains("#SS") && this.testStatusCode < TestStatus.SAMPLE_STARTED.code -> { + (resultData.contains("#SS") || resultData.contains("#SS1")) && this.testStatusCode < TestStatus.SAMPLE_STARTED.code -> { this.testStatusCode = TestStatus.SAMPLE_STARTED.code activity?.runOnUiThread { binding.tvSubtitle4.text = getString(R.string.sample_started) @@ -402,7 +399,7 @@ class HemoCubeFragment : Fragment() { } } - resultData.contains("#SC") && this.testStatusCode < TestStatus.SAMPLE_COMPLETED.code -> { + (resultData.contains("#SC") || resultData.contains("#SC1")) && this.testStatusCode < TestStatus.SAMPLE_COMPLETED.code -> { this.testStatusCode = TestStatus.SAMPLE_COMPLETED.code hemoCubeViewModel.messages.postValue( getString(R.string.sample_completed) + "\n" + getString(R.string.gathering_data)) @@ -574,7 +571,7 @@ class HemoCubeFragment : Fragment() { } fun processHardwareId(resultData: String) { - val hardwareId = "HCV-000-3001" //extractMiddleString(resultData) + val hardwareId = extractMiddleString(resultData) if (!hardwareId.isNullOrBlank()) { updateDeviceId(hardwareId) @@ -582,17 +579,17 @@ class HemoCubeFragment : Fragment() { binding.btnPlacebuffer.visibility = View.VISIBLE } hemoCubeViewModel.messages.postValue(getString(R.string.start)) - - if (!Constants.DEVICE_CONFIGURATION.containsKey(deviceHardwareId)) { - deviceHardwareId = "HCV-000-3001" - allErrorMessages += "Calibration configuration for this device id is not found\n" - } - if (!Constants.BUFFER_INTENSITY_THRESHOLDS.containsKey(deviceHardwareId)) { - allErrorMessages += "ADC thresholds for this device id are not found\n" - } } else { hemoCubeViewModel.messages.postValue("Config error") } + + if (!Constants.DEVICE_CONFIGURATION.containsKey(deviceHardwareId)) { + deviceHardwareId = "HCV-000-3001" + allErrorMessages += "Calibration configuration for this device id is not found\n" + } + if (!Constants.BUFFER_INTENSITY_THRESHOLDS.containsKey(deviceHardwareId)) { + allErrorMessages += "ADC thresholds for this device id are not found\n" + } } fun extractMiddleString(input: String): String? { @@ -696,25 +693,25 @@ class HemoCubeFragment : Fragment() { val slope1 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(1)?.get(0) val intercept1 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(1)?.get(1) - val _hb1 = (led3Average - intercept1!!) / slope1!! + val calculatedHb1 = (led1Average - intercept1!!) / slope1!! val slope2 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(0) val intercept = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(1) - val _hb2 = (led4Average - intercept!!) / slope2!! + val calculatedHb2 = (led2Average - intercept!!) / slope2!! val slope3 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(2)?.get(0) val intercept3 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(2)?.get(1) - val _hb3 = (led3Average - intercept3!!) / slope3!! + val calculatedHb3 = (led3Average - intercept3!!) / slope3!! val slope4 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(0) val intercept4 = Constants.DEVICE_HB_PARAMETERS[deviceHardwareId]?.get(3)?.get(1) - val _hb4 = (led4Average - intercept4!!) / slope4!! + val calculatedHb4 = (led4Average - intercept4!!) / slope4!! - _predictedDenovixRatio = fittedAbs3.div(fittedAbs1) + calculatedPredictedDenovixRatio = fittedAbs3.div(fittedAbs1) val slope = (led1Average - led2Average) / (435 - 415) - val _slopeRatio = abs(led3Average / slope) - val slopeClass = slopeRatioClassification(_slopeRatio) + val calculatedSlopeRatio = abs(led3Average / slope) + val slopeClass = slopeRatioClassification(calculatedSlopeRatio) if (fittedAbs1 <= fittedAbs2) { validationError = true @@ -733,7 +730,7 @@ class HemoCubeFragment : Fragment() { } } - if ((led1Average < 0.7 || led2Average < 0.7 || led3Average < 0.7 || led4Average < 0.7) && _slopeRatio > 35.0) { + if ((led1Average < 0.7 || led2Average < 0.7 || led3Average < 0.7 || led4Average < 0.7) && calculatedSlopeRatio > 35.0) { validationError = true activity?.runOnUiThread { binding.errorMessage.text = "Severely Low Hb. Repeat test with 12 ul in 2 ml Buffer" @@ -769,12 +766,12 @@ class HemoCubeFragment : Fragment() { this.abs2 = fittedAbs2 this.abs3 = fittedAbs3 this.abs4 = fittedAbs4 - this.hb3 = _hb3 - this.hb4 = _hb4 + this.hb3 = calculatedHb3 + this.hb4 = calculatedHb4 this.deviceRatio = deviceRatio this.calculatedRatio = calculateRatio(deviceRatio) - this.predictedDenovixRatio = _predictedDenovixRatio - this.slopeRatio = _slopeRatio + this.predictedDenovixRatio = calculatedPredictedDenovixRatio + this.slopeRatio = calculatedSlopeRatio this.coefficients = currentDeviceData?.coefficients?.get(0) .toString() + ", " + currentDeviceData?.coefficients?.get(1).toString() this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio) @@ -783,7 +780,7 @@ class HemoCubeFragment : Fragment() { this.classificationResult = deviceRatioClass //findResult(calculatedRatio) hemoCubeViewModel.messages.postValue("${this.deviceRatioClass} ${if (led4Average < 0.17) " - Low Hb" else ""}\n") if (DataHolder.hemoCubeTestData?.testType == "HB") - hemoCubeViewModel.messages.postValue("HB: $_hb4") + hemoCubeViewModel.messages.postValue("HB: $calculatedHb4") this.errorMessages = allErrorMessages this.resultData = deviceLog this.batteryLevel = hemoCubeViewModel.getBatteryLevel().toString() diff --git a/app/src/test/java/com/example/hpostesting/HemocubeViewModelTest.kt b/app/src/test/java/com/example/hpostesting/HemocubeViewModelTest.kt index 79e04e7..1def929 100644 --- a/app/src/test/java/com/example/hpostesting/HemocubeViewModelTest.kt +++ b/app/src/test/java/com/example/hpostesting/HemocubeViewModelTest.kt @@ -1,27 +1,20 @@ package com.example.hpostesting import android.content.Context -import android.os.Build import androidx.arch.core.executor.testing.InstantTaskExecutorRule import androidx.lifecycle.Observer -import androidx.work.Configuration -import androidx.work.testing.SynchronousExecutor -import androidx.work.testing.WorkManagerTestInitHelper import com.example.hpostesting.data.Result import com.example.hpostesting.data.model.login.LoginResponse import com.example.hpostesting.data.repository.Repository import com.example.hpostesting.domain.LogFileManager import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.util.TestCoroutineRule -import io.mockk.MockKAnnotations -import io.mockk.coEvery -import io.mockk.coVerify import io.mockk.every import io.mockk.impl.annotations.MockK import io.mockk.mockk import io.mockk.verify +import junit.framework.TestCase import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.runBlockingTest import org.junit.After import org.junit.Before import org.junit.Rule @@ -29,35 +22,34 @@ import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config -import java.io.File -//@RunWith(RobolectricTestRunner::class) -//@Config(manifest = Config.NONE) -//@ExperimentalCoroutinesApi -//class HemocubeViewModelTest { -// -// @get:Rule -// val instantTaskExecutorRule = InstantTaskExecutorRule() -// -// @get:Rule -// val coroutineRule = TestCoroutineRule() -// -// @MockK(relaxed = true) -// lateinit var repository: Repository -// -// @MockK(relaxed = true) -// lateinit var logFileManager: LogFileManager -// -// @MockK(relaxed = true) -// lateinit var context: Context -// -// @MockK(relaxed = true) -// lateinit var observer: Observer> -// -// private lateinit var viewModel: HemoCubeViewModel -// -// @Before -// fun setup() { +@RunWith(RobolectricTestRunner::class) +@Config(manifest = Config.NONE) +@ExperimentalCoroutinesApi +class HemocubeViewModelTest { + + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @get:Rule + val coroutineRule = TestCoroutineRule() + + @MockK(relaxed = true) + lateinit var repository: Repository + + @MockK(relaxed = true) + lateinit var logFileManager: LogFileManager + + @MockK(relaxed = true) + lateinit var context: Context + + @MockK(relaxed = true) + lateinit var observer: Observer> + + private lateinit var viewModel: HemoCubeViewModel + + @Before + fun setup() { // MockKAnnotations.init(this) // // val config = Configuration.Builder() @@ -78,13 +70,34 @@ import java.io.File // context // ) // viewModel.loginResponse.observeForever(observer) -// } -// -// @After -// fun teardown() { + } + + @After + fun teardown() { // viewModel.loginResponse.removeObserver(observer) -// } -// + } + + @Test + fun `testAddNumbers in HemocubeViewModelTest`() { + // Create a mock of the Calculator class using Mockito-Kotlin + val calculatorMock = mockk() + + // Define the behavior of the add method on the mock + every { calculatorMock.add(2, 3) } returns 5 + + // Create an instance of MathApplication with the mock Calculator + val mathApplication = MathApplication(calculatorMock) + + // Perform the test using the MathApplication + val result = mathApplication.addNumbers(2, 3) + + // Verify that the add method of the mock was called with the correct parameters + verify { calculatorMock.add(2, 3) } + + // Verify the result of the test + TestCase.assertEquals(5, result) + } + // @Test // fun `login() should update LiveData with success`() = coroutineRule.runBlockingTest { // @@ -124,7 +137,7 @@ import java.io.File // viewModel.uploadLogs() // // // Assert -// verify { observer.onChanged(response) } +// verify { observer.onChanged(response as Result) } // } // // @Test @@ -141,4 +154,4 @@ import java.io.File // // Assert // verify { observer.onChanged(response) } // } -//} \ No newline at end of file +} \ No newline at end of file diff --git a/app/src/test/java/com/example/hpostesting/MathApplication.kt b/app/src/test/java/com/example/hpostesting/MathApplication.kt new file mode 100644 index 0000000..a2c88dd --- /dev/null +++ b/app/src/test/java/com/example/hpostesting/MathApplication.kt @@ -0,0 +1,15 @@ +package com.example.hpostesting + + +class Calculator { + fun add(a: Int, b: Int): Int { + return a + b + } +} + + +class MathApplication(private val calculator: Calculator) { + fun addNumbers(a: Int, b: Int): Int { + return calculator.add(a, b) + } +} \ No newline at end of file diff --git a/app/src/test/java/com/example/hpostesting/MathApplicationTest.kt b/app/src/test/java/com/example/hpostesting/MathApplicationTest.kt new file mode 100644 index 0000000..a27aef5 --- /dev/null +++ b/app/src/test/java/com/example/hpostesting/MathApplicationTest.kt @@ -0,0 +1,31 @@ +package com.example.hpostesting + +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import junit.framework.TestCase.assertEquals +import org.junit.Test + +class MathApplicationTest { + + @Test + fun testAddNumbers() { + // Create a mock of the Calculator class using Mockito-Kotlin + val calculatorMock = mockk() + + // Define the behavior of the add method on the mock + every { calculatorMock.add(2, 3) } returns 5 + + // Create an instance of MathApplication with the mock Calculator + val mathApplication = MathApplication(calculatorMock) + + // Perform the test using the MathApplication + val result = mathApplication.addNumbers(2, 3) + + // Verify that the add method of the mock was called with the correct parameters + verify { calculatorMock.add(2, 3) } + + // Verify the result of the test + assertEquals(5, result) + } +} \ No newline at end of file diff --git a/app/src/test/java/com/example/hpostesting/NetworkStatusLiveDataTest.kt b/app/src/test/java/com/example/hpostesting/NetworkStatusLiveDataTest.kt new file mode 100644 index 0000000..fc3827c --- /dev/null +++ b/app/src/test/java/com/example/hpostesting/NetworkStatusLiveDataTest.kt @@ -0,0 +1,77 @@ +package com.example.hpostesting + +import android.content.Context +import android.net.ConnectivityManager +import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import junit.framework.TestCase +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.junit.MockitoJUnitRunner + + +@RunWith(MockitoJUnitRunner::class) +class NetworkStatusLiveDataTest { + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @Mock + private lateinit var mockContext: Context + + @Mock + private lateinit var mockConnectivityManager: ConnectivityManager + + @Before + fun setUp() { +// mockContext = ApplicationProvider.getApplicationContext() +// mockConnectivityManager = mockContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + } + + @Test + fun testAddNumbers() { + // Create a mock of the Calculator class using Mockito-Kotlin + val calculatorMock = mockk() + + // Define the behavior of the add method on the mock + every { calculatorMock.add(2, 3) } returns 5 + + // Create an instance of MathApplication with the mock Calculator + val mathApplication = MathApplication(calculatorMock) + + // Perform the test using the MathApplication + val result = mathApplication.addNumbers(2, 3) + + // Verify that the add method of the mock was called with the correct parameters + verify { calculatorMock.add(2, 3) } + + // Verify the result of the test + TestCase.assertEquals(5, result) + } + +// @Test +// fun testNetworkStatusLiveData() { +// // Assuming mockConnectivityManager is a mocked ConnectivityManager instance +// val mockNetwork = mock(Network::class.java) +// val mockNetworkCapabilities = mock(NetworkCapabilities::class.java) +// +// // Define desired capabilities +// `when`(mockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)).thenReturn(true) +// `when`(mockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)).thenReturn(true) +// +// // Set up network to return mocked capabilities +// `when`(mockConnectivityManager.activeNetwork).thenReturn(mockNetwork) +// `when`(mockConnectivityManager.getNetworkCapabilities(mockNetwork)).thenReturn(mockNetworkCapabilities) +// +// // Act +// val networkStatusLiveData = NetworkStatusLiveData(mockContext) +// val isConnected = networkStatusLiveData.value +// +// // Assert +// assertTrue("Network should be connected", isConnected!!) +// } +} \ No newline at end of file