From 2c8c32336e34de98eeeb73e10d06177f77c06b71 Mon Sep 17 00:00:00 2001 From: fsharpasharp Date: Wed, 9 Dec 2020 09:55:59 +0100 Subject: [PATCH 1/2] Add tests for ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider. --- domain/BUILD.bazel | 9 + ...ntainAtLeastOneOfRuleClassifierProvider.kt | 1 - ...nAtLeastOneOfRuleClassifierProviderTest.kt | 172 ++++++++++++++++++ 3 files changed, 181 insertions(+), 1 deletion(-) mode change 100644 => 100755 domain/BUILD.bazel create mode 100644 domain/src/test/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest.kt diff --git a/domain/BUILD.bazel b/domain/BUILD.bazel old mode 100644 new mode 100755 index 2ab358b4514..987bad3246c --- a/domain/BUILD.bazel +++ b/domain/BUILD.bazel @@ -129,6 +129,15 @@ domain_test( deps = TEST_DEPS, ) +domain_test( + name = "ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest", + srcs = [ + "src/test/java/org/oppia/android/domain/classify/rules/textinput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest.kt", + ], + test_class = "org.oppia.android.domain.classify.rules.textinput.ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest", + deps = TEST_DEPS, +) + domain_test( name = "TextInputEqualsRuleClassifierProviderTest", srcs = [ diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider.kt index 0b2ce625d99..d832f865683 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider.kt @@ -26,7 +26,6 @@ internal class ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvide ) } - // TODO(#210): Add tests for this classifier. override fun matches(answer: StringList, input: StringList): Boolean { return answer.htmlList.toSet().intersect(input.htmlList).isEmpty() } diff --git a/domain/src/test/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest.kt b/domain/src/test/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest.kt new file mode 100644 index 00000000000..e0761d5ecbd --- /dev/null +++ b/domain/src/test/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest.kt @@ -0,0 +1,172 @@ +package org.oppia.android.domain.classify.rules.itemselectioninput + +import android.app.Application +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat +import dagger.BindsInstance +import dagger.Component +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.oppia.android.domain.classify.InteractionObjectTestBuilder +import org.robolectric.annotation.Config +import org.robolectric.annotation.LooperMode +import javax.inject.Inject +import javax.inject.Singleton + +/** Tests for [ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider]. */ +@RunWith(AndroidJUnit4::class) +@LooperMode(LooperMode.Mode.PAUSED) +@Config(manifest = Config.NONE) +class ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest { + + private val ITEM_SELECTION_SET_5 = + InteractionObjectTestBuilder.createHtmlStringListInteractionObject( + InteractionObjectTestBuilder + .createHtmlStringList("test1", "test2", "test3", "test4", "test5") + ) + + private val ITEM_SELECTION_SET_SUBSET = + InteractionObjectTestBuilder.createHtmlStringListInteractionObject( + InteractionObjectTestBuilder + .createHtmlStringList("test1") + ) + + private val ITEM_SELECTION_SET_ONE_ELEMENT_PRESENT = + InteractionObjectTestBuilder.createHtmlStringListInteractionObject( + InteractionObjectTestBuilder + .createHtmlStringList("test1", "test6") + ) + + private val ITEM_SELECTION_SET_TWO_ELEMENTS_PRESENT_NO_EXTRA_ELEMENT = + InteractionObjectTestBuilder.createHtmlStringListInteractionObject( + InteractionObjectTestBuilder + .createHtmlStringList("test1", "test2") + ) + + private val ITEM_SELECTION_SET_TWO_ELEMENTS_PRESENT_WITH_EXTRA_ELEMENT = + InteractionObjectTestBuilder.createHtmlStringListInteractionObject( + InteractionObjectTestBuilder + .createHtmlStringList("test1", "test2", "test6") + ) + + private val ITEM_SELECTION_SET_EMPTY = + InteractionObjectTestBuilder.createHtmlStringListInteractionObject( + InteractionObjectTestBuilder + .createHtmlStringList() + ) + + private val ITEM_SELECTION_SET_EXCLUSIVE = + InteractionObjectTestBuilder.createHtmlStringListInteractionObject( + InteractionObjectTestBuilder + .createHtmlStringList("test6") + ) + + @Inject + internal lateinit var itemSelectionInputDesNotContainAtLeastOneOfRuleClassifierProvider: + ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider + + private val inputDoesNotContainAtLeastOneOfRuleClassifier by lazy { + itemSelectionInputDesNotContainAtLeastOneOfRuleClassifierProvider.createRuleClassifier() + } + + @Before + fun setUp() { + setUpTestApplicationComponent() + } + + @Test + fun testItemSet_setAnswer_inputIsASubset_answerContainsInput() { + val inputs = mapOf("x" to ITEM_SELECTION_SET_SUBSET) + + val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( + answer = ITEM_SELECTION_SET_5, + inputs = inputs + ) + + assertThat(matches).isFalse() + } + + @Test + fun testItemSet_setAnswer_inputHasOneElementInSet_answerContainsInput() { + val inputs = mapOf("x" to ITEM_SELECTION_SET_ONE_ELEMENT_PRESENT) + + val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( + answer = ITEM_SELECTION_SET_5, + inputs = inputs + ) + + assertThat(matches).isFalse() + } + + @Test + fun testItemSet_setAnswer_inputHasTwoElementsInSetNoneExtra_answerContainsInput() { + val inputs = mapOf("x" to ITEM_SELECTION_SET_TWO_ELEMENTS_PRESENT_NO_EXTRA_ELEMENT) + + val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( + answer = ITEM_SELECTION_SET_5, + inputs = inputs + ) + + assertThat(matches).isFalse() + } + + @Test + fun testItemSet_setAnswer_inputHasTwoElementsInSetOneExtra_answerContainsInput() { + val inputs = mapOf("x" to ITEM_SELECTION_SET_TWO_ELEMENTS_PRESENT_WITH_EXTRA_ELEMENT) + + val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( + answer = ITEM_SELECTION_SET_5, + inputs = inputs + ) + + assertThat(matches).isFalse() + } + + @Test + fun testItemSet_setAnswer_inputIsEmptySet_answerDoesNotContainInput() { + val inputs = mapOf("x" to ITEM_SELECTION_SET_EMPTY) + + val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( + answer = ITEM_SELECTION_SET_5, + inputs = inputs + ) + + assertThat(matches).isTrue() + } + + @Test + fun testItemSet_setAnswer_inputIsExclusiveOfSet_answerDoesNotContainInput() { + val inputs = mapOf("x" to ITEM_SELECTION_SET_EXCLUSIVE) + + val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( + answer = ITEM_SELECTION_SET_5, + inputs = inputs + ) + + assertThat(matches).isTrue() + } + + private fun setUpTestApplicationComponent() { + DaggerItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest_TestApplicationComponent // ktlint-disable max-line-length + .builder() + .setApplication(ApplicationProvider.getApplicationContext()) + .build() + .inject(this) + } + + @Singleton + @Component(modules = []) + interface TestApplicationComponent { + @Component.Builder + interface Builder { + @BindsInstance + fun setApplication(application: Application): Builder + + fun build(): TestApplicationComponent + } + + fun inject(test: ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest) + } +} From 5cec45e36cec532eed0e53a9a2e14a02ddbd0f26 Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 16 Dec 2020 04:33:12 +0100 Subject: [PATCH 2/2] Add additional tests and rename variables. --- ...nAtLeastOneOfRuleClassifierProviderTest.kt | 131 +++++++++++++++--- 1 file changed, 112 insertions(+), 19 deletions(-) diff --git a/domain/src/test/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest.kt b/domain/src/test/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest.kt index e0761d5ecbd..2b932b3c583 100644 --- a/domain/src/test/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest.kt +++ b/domain/src/test/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest.kt @@ -12,8 +12,12 @@ import org.junit.runner.RunWith import org.oppia.android.domain.classify.InteractionObjectTestBuilder import org.robolectric.annotation.Config import org.robolectric.annotation.LooperMode +import java.lang.IllegalStateException import javax.inject.Inject import javax.inject.Singleton +import kotlin.reflect.KClass +import kotlin.reflect.full.cast +import kotlin.test.fail /** Tests for [ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider]. */ @RunWith(AndroidJUnit4::class) @@ -21,48 +25,51 @@ import javax.inject.Singleton @Config(manifest = Config.NONE) class ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest { - private val ITEM_SELECTION_SET_5 = + private val ITEM_SET_12345 = InteractionObjectTestBuilder.createHtmlStringListInteractionObject( InteractionObjectTestBuilder .createHtmlStringList("test1", "test2", "test3", "test4", "test5") ) - private val ITEM_SELECTION_SET_SUBSET = + private val ITEM_SET_1 = InteractionObjectTestBuilder.createHtmlStringListInteractionObject( InteractionObjectTestBuilder .createHtmlStringList("test1") ) - private val ITEM_SELECTION_SET_ONE_ELEMENT_PRESENT = + private val ITEM_SET_16 = InteractionObjectTestBuilder.createHtmlStringListInteractionObject( InteractionObjectTestBuilder .createHtmlStringList("test1", "test6") ) - private val ITEM_SELECTION_SET_TWO_ELEMENTS_PRESENT_NO_EXTRA_ELEMENT = + private val ITEM_SET_12 = InteractionObjectTestBuilder.createHtmlStringListInteractionObject( InteractionObjectTestBuilder .createHtmlStringList("test1", "test2") ) - private val ITEM_SELECTION_SET_TWO_ELEMENTS_PRESENT_WITH_EXTRA_ELEMENT = + private val ITEM_SET_126 = InteractionObjectTestBuilder.createHtmlStringListInteractionObject( InteractionObjectTestBuilder .createHtmlStringList("test1", "test2", "test6") ) - private val ITEM_SELECTION_SET_EMPTY = + private val ITEM_SET_EMPTY = InteractionObjectTestBuilder.createHtmlStringListInteractionObject( InteractionObjectTestBuilder .createHtmlStringList() ) - private val ITEM_SELECTION_SET_EXCLUSIVE = + private val ITEM_SET_6 = InteractionObjectTestBuilder.createHtmlStringListInteractionObject( InteractionObjectTestBuilder .createHtmlStringList("test6") ) + private val DIFFERENT_INTERACTION_OBJECT_TYPE = + InteractionObjectTestBuilder.createInt(0) + @Inject internal lateinit var itemSelectionInputDesNotContainAtLeastOneOfRuleClassifierProvider: ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider @@ -78,10 +85,10 @@ class ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest { @Test fun testItemSet_setAnswer_inputIsASubset_answerContainsInput() { - val inputs = mapOf("x" to ITEM_SELECTION_SET_SUBSET) + val inputs = mapOf("x" to ITEM_SET_1) val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( - answer = ITEM_SELECTION_SET_5, + answer = ITEM_SET_12345, inputs = inputs ) @@ -90,10 +97,10 @@ class ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest { @Test fun testItemSet_setAnswer_inputHasOneElementInSet_answerContainsInput() { - val inputs = mapOf("x" to ITEM_SELECTION_SET_ONE_ELEMENT_PRESENT) + val inputs = mapOf("x" to ITEM_SET_16) val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( - answer = ITEM_SELECTION_SET_5, + answer = ITEM_SET_12345, inputs = inputs ) @@ -102,10 +109,10 @@ class ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest { @Test fun testItemSet_setAnswer_inputHasTwoElementsInSetNoneExtra_answerContainsInput() { - val inputs = mapOf("x" to ITEM_SELECTION_SET_TWO_ELEMENTS_PRESENT_NO_EXTRA_ELEMENT) + val inputs = mapOf("x" to ITEM_SET_12) val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( - answer = ITEM_SELECTION_SET_5, + answer = ITEM_SET_12345, inputs = inputs ) @@ -114,10 +121,10 @@ class ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest { @Test fun testItemSet_setAnswer_inputHasTwoElementsInSetOneExtra_answerContainsInput() { - val inputs = mapOf("x" to ITEM_SELECTION_SET_TWO_ELEMENTS_PRESENT_WITH_EXTRA_ELEMENT) + val inputs = mapOf("x" to ITEM_SET_126) val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( - answer = ITEM_SELECTION_SET_5, + answer = ITEM_SET_12345, inputs = inputs ) @@ -126,10 +133,10 @@ class ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest { @Test fun testItemSet_setAnswer_inputIsEmptySet_answerDoesNotContainInput() { - val inputs = mapOf("x" to ITEM_SELECTION_SET_EMPTY) + val inputs = mapOf("x" to ITEM_SET_EMPTY) val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( - answer = ITEM_SELECTION_SET_5, + answer = ITEM_SET_12345, inputs = inputs ) @@ -138,16 +145,88 @@ class ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest { @Test fun testItemSet_setAnswer_inputIsExclusiveOfSet_answerDoesNotContainInput() { - val inputs = mapOf("x" to ITEM_SELECTION_SET_EXCLUSIVE) + val inputs = mapOf("x" to ITEM_SET_6) + + val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( + answer = ITEM_SET_12345, + inputs = inputs + ) + + assertThat(matches).isTrue() + } + + @Test + fun testItemSet_setAnswerIsEmpty_inputIsNonEmpty_answerDoesNotContainInput() { + val inputs = mapOf("x" to ITEM_SET_12345) val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( - answer = ITEM_SELECTION_SET_5, + answer = ITEM_SET_EMPTY, inputs = inputs ) assertThat(matches).isTrue() } + @Test + fun testItemSet_setAnswer_inputIsASuperset_answerContainsInput() { + val inputs = mapOf("x" to ITEM_SET_12345) + + val matches = inputDoesNotContainAtLeastOneOfRuleClassifier.matches( + answer = ITEM_SET_12, + inputs = inputs + ) + + assertThat(matches).isFalse() + } + + @Test + fun testItemSet_inputIsMissing_throwsException() { + val inputs = mapOf("y" to ITEM_SET_1) + + val exception = assertThrows(IllegalStateException::class) { + inputDoesNotContainAtLeastOneOfRuleClassifier.matches( + answer = ITEM_SET_12345, + inputs = inputs + ) + } + + assertThat(exception) + .hasMessageThat() + .contains("Expected classifier inputs to contain parameter with name 'x'") + } + + @Test + fun testItemSet_inputHasTheWrongType_throwsException() { + val inputs = mapOf("x" to DIFFERENT_INTERACTION_OBJECT_TYPE) + + val exception = assertThrows(IllegalStateException::class) { + inputDoesNotContainAtLeastOneOfRuleClassifier.matches( + answer = ITEM_SET_12345, + inputs = inputs + ) + } + + assertThat(exception) + .hasMessageThat() + .contains("Expected input value to be of type SET_OF_HTML_STRING") + } + + @Test + fun testItemSet_answerHasTheWrongType_throwsException() { + val inputs = mapOf("x" to ITEM_SET_12345) + + val exception = assertThrows(IllegalStateException::class) { + inputDoesNotContainAtLeastOneOfRuleClassifier.matches( + answer = DIFFERENT_INTERACTION_OBJECT_TYPE, + inputs = inputs + ) + } + + assertThat(exception) + .hasMessageThat() + .contains("Expected answer to be of type SET_OF_HTML_STRING") + } + private fun setUpTestApplicationComponent() { DaggerItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest_TestApplicationComponent // ktlint-disable max-line-length .builder() @@ -156,6 +235,20 @@ class ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest { .inject(this) } + // TODO(#89): Move to a common test library. + private fun assertThrows(type: KClass, operation: () -> Unit): T { + try { + operation() + fail("Expected to encounter exception of $type") + } catch (t: Throwable) { + if (type.isInstance(t)) { + return type.cast(t) + } + // Unexpected exception; throw it. + throw t + } + } + @Singleton @Component(modules = []) interface TestApplicationComponent {