From f13ac52b6a0a81706566d5709921bbbba9ec4a98 Mon Sep 17 00:00:00 2001 From: Ayush Yadav <143514610+theayushyadav11@users.noreply.github.com> Date: Fri, 21 Feb 2025 10:57:17 +0530 Subject: [PATCH] Fixes #4132: Added tests for MathParsingErrorSubject. (#5684) Fixes #4132: This pull request focuses on adding comprehensive tests for the `MathParsingErrorSubject` class and making necessary adjustments to the related files. The most important changes include the removal of an exemption for `MathParsingErrorSubject.kt`, the addition of a new test file for `MathParsingErrorSubject`, and the creation of a corresponding Bazel test target. ### Test Enhancements: * [`testing/src/main/java/org/oppia/android/testing/math/MathParsingErrorSubject.kt`](diffhunk://#diff-c53693be09949f0e5f37517762c04d2ac4f8eb09049987bfcfcaca1243d51d3aL46-L47): Removed the TODO comment indicating the need for tests. * [`testing/src/test/java/org/oppia/android/testing/math/MathParsingErrorSubjectTest.kt`](diffhunk://#diff-1110331e8184259d41c97f5541a1ab1b71ec94e2942f49e0b6c7df0533bd049eR1-R293): Added a new test file containing various unit tests for the `MathParsingErrorSubject` class. ### Configuration Updates: * [`testing/src/test/java/org/oppia/android/testing/math/BUILD.bazel`](diffhunk://#diff-8a86bceb0e654069d42dcb4e76a52f65aeea3bc7d76a9cdff53f5e4bdde93f08R70-R85): Added a new Bazel test target for `MathParsingErrorSubjectTest`. ### Cleanup: * [`scripts/assets/test_file_exemptions.textproto`](diffhunk://#diff-6ed782dd71126d847e7bac39eca30f830be55b72aa10b7e944612f2463003e24L4105-L4108): Removed the test file exemption for `MathParsingErrorSubject.kt`. #### Screenshot of the pasing tests: ![Screenshot from 2025-02-01 19-58-33](https://github.com/user-attachments/assets/fa770881-5b11-4bc0-907e-a63dbbe4e2ca) ## Essential Checklist - [x] The PR title and explanation each start with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".) - [x] Any changes to [scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets) files have their rationale included in the PR explanation. - [x] The PR follows the [style guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide). - [x] The PR does not contain any unnecessary code changes from Android Studio ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)). - [x] The PR is made from a branch that's **not** called "develop" and is up-to-date with "develop". - [x] The PR is **assigned** to the appropriate reviewers ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)). --------- Co-authored-by: theayushyadav11 Co-authored-by: Adhiambo Peres <59600948+adhiamboperes@users.noreply.github.com> --- scripts/assets/test_file_exemptions.textproto | 4 - .../testing/math/MathParsingErrorSubject.kt | 2 - .../oppia/android/testing/math/BUILD.bazel | 16 + .../math/MathParsingErrorSubjectTest.kt | 300 ++++++++++++++++++ 4 files changed, 316 insertions(+), 6 deletions(-) create mode 100644 testing/src/test/java/org/oppia/android/testing/math/MathParsingErrorSubjectTest.kt diff --git a/scripts/assets/test_file_exemptions.textproto b/scripts/assets/test_file_exemptions.textproto index 02d22431745..2b4731054d5 100644 --- a/scripts/assets/test_file_exemptions.textproto +++ b/scripts/assets/test_file_exemptions.textproto @@ -4102,10 +4102,6 @@ test_file_exemption { exempted_file_path: "testing/src/main/java/org/oppia/android/testing/math/ComparableOperationSubject.kt" test_file_not_required: true } -test_file_exemption { - exempted_file_path: "testing/src/main/java/org/oppia/android/testing/math/MathParsingErrorSubject.kt" - test_file_not_required: true -} test_file_exemption { exempted_file_path: "testing/src/main/java/org/oppia/android/testing/mockito/MockitoKotlinHelper.kt" test_file_not_required: true diff --git a/testing/src/main/java/org/oppia/android/testing/math/MathParsingErrorSubject.kt b/testing/src/main/java/org/oppia/android/testing/math/MathParsingErrorSubject.kt index 9c62f183aca..8a577d8265d 100644 --- a/testing/src/main/java/org/oppia/android/testing/math/MathParsingErrorSubject.kt +++ b/testing/src/main/java/org/oppia/android/testing/math/MathParsingErrorSubject.kt @@ -43,8 +43,6 @@ import org.oppia.android.util.math.MathParsingError.UnbalancedParenthesesError import org.oppia.android.util.math.MathParsingError.UnnecessarySymbolsError import org.oppia.android.util.math.MathParsingError.VariableInNumericExpressionError -// TODO(#4132): Add tests for this class. - /** * Truth subject for verifying properties of [MathParsingError]s. * diff --git a/testing/src/test/java/org/oppia/android/testing/math/BUILD.bazel b/testing/src/test/java/org/oppia/android/testing/math/BUILD.bazel index 63cb143e73e..cdc91cd8b0f 100644 --- a/testing/src/test/java/org/oppia/android/testing/math/BUILD.bazel +++ b/testing/src/test/java/org/oppia/android/testing/math/BUILD.bazel @@ -96,3 +96,19 @@ oppia_android_test( "//third_party:robolectric_android-all", ], ) + +oppia_android_test( + name = "MathParsingErrorSubjectTest", + srcs = ["MathParsingErrorSubjectTest.kt"], + custom_package = "org.oppia.android.testing.math", + test_class = "org.oppia.android.testing.math.MathParsingErrorSubjectTest", + test_manifest = "//testing:test_manifest", + deps = [ + "//model/src/main/proto:math_java_proto_lite", + "//testing/src/main/java/org/oppia/android/testing/math:math_parsing_error_subject", + "//testing/src/main/java/org/oppia/android/testing/robolectric:test_module", + "//third_party:com_google_truth_truth", + "//third_party:junit_junit", + "//third_party:robolectric_android-all", + ], +) diff --git a/testing/src/test/java/org/oppia/android/testing/math/MathParsingErrorSubjectTest.kt b/testing/src/test/java/org/oppia/android/testing/math/MathParsingErrorSubjectTest.kt new file mode 100644 index 00000000000..847a2b804d5 --- /dev/null +++ b/testing/src/test/java/org/oppia/android/testing/math/MathParsingErrorSubjectTest.kt @@ -0,0 +1,300 @@ +package org.oppia.android.testing.math + +import org.junit.Assert.assertThrows +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.oppia.android.app.model.MathBinaryOperation +import org.oppia.android.app.model.MathExpression +import org.oppia.android.app.model.Real +import org.oppia.android.testing.math.MathParsingErrorSubject.Companion.assertThat +import org.oppia.android.util.math.MathParsingError.DisabledVariablesInUseError +import org.oppia.android.util.math.MathParsingError.EquationHasTooManyEqualsError +import org.oppia.android.util.math.MathParsingError.EquationIsMissingEqualsError +import org.oppia.android.util.math.MathParsingError.EquationMissingLhsOrRhsError +import org.oppia.android.util.math.MathParsingError.ExponentIsVariableExpressionError +import org.oppia.android.util.math.MathParsingError.ExponentTooLargeError +import org.oppia.android.util.math.MathParsingError.FunctionNameIncompleteError +import org.oppia.android.util.math.MathParsingError.GenericError +import org.oppia.android.util.math.MathParsingError.HangingSquareRootError +import org.oppia.android.util.math.MathParsingError.InvalidFunctionInUseError +import org.oppia.android.util.math.MathParsingError.MultipleRedundantParenthesesError +import org.oppia.android.util.math.MathParsingError.NestedExponentsError +import org.oppia.android.util.math.MathParsingError.NoVariableOrNumberAfterBinaryOperatorError +import org.oppia.android.util.math.MathParsingError.NoVariableOrNumberBeforeBinaryOperatorError +import org.oppia.android.util.math.MathParsingError.NumberAfterVariableError +import org.oppia.android.util.math.MathParsingError.SingleRedundantParenthesesError +import org.oppia.android.util.math.MathParsingError.SpacesBetweenNumbersError +import org.oppia.android.util.math.MathParsingError.SubsequentBinaryOperatorsError +import org.oppia.android.util.math.MathParsingError.SubsequentUnaryOperatorsError +import org.oppia.android.util.math.MathParsingError.TermDividedByZeroError +import org.oppia.android.util.math.MathParsingError.UnbalancedParenthesesError +import org.oppia.android.util.math.MathParsingError.UnnecessarySymbolsError +import org.oppia.android.util.math.MathParsingError.VariableInNumericExpressionError + +/** Tests for [MathParsingErrorSubject]. */ +@RunWith(JUnit4::class) +class MathParsingErrorSubjectTest { + + @Test + fun testMathParsingErrorSubject_hasSpaceBetweenNumbersError() { + val error = SpacesBetweenNumbersError + assertThat(error).isSpacesBetweenNumbers() + } + + @Test + fun testMathParsingErrorSubject_hasSpaceBetweenNumbersError_fails() { + val error = UnbalancedParenthesesError + assertThrows(AssertionError::class.java) { + assertThat(error).isSpacesBetweenNumbers() + } + } + + @Test + fun testMathParsingErrorSubject_hasUnbalancedParenthesesError() { + val error = UnbalancedParenthesesError + assertThat(error).isUnbalancedParentheses() + } + + @Test + fun testMathParsingErrorSubject_hasUnbalancedParenthesesError_fails() { + val error = SpacesBetweenNumbersError + assertThrows(AssertionError::class.java) { + assertThat(error).isUnbalancedParentheses() + } + } + + @Test + fun testMathParsingErrorSubject_hasSingleRedundantParenthesesWitDetails() { + val constant = Real.newBuilder().setInteger(5).build() + val expression = MathExpression.newBuilder().setConstant(constant).build() + val group = MathExpression.newBuilder().setGroup(expression).build() + val error = SingleRedundantParenthesesError("(5)", group) + + assertThat(error).isSingleRedundantParenthesesThat().apply { + hasRawExpressionThat().isEqualTo("(5)") + hasExpressionThat().hasStructureThatMatches { + group { + constant { + hasExpressionThat().evaluatesToIntegerThat().isEqualTo(5) + } + } + } + } + } + + @Test + fun testMathParsingErrorSubject_hasMultipleRedundantParenthesesWithDetails() { + val constant = Real.newBuilder().setInteger(5).build() + val expression = MathExpression.newBuilder().setConstant(constant).build() + val groupOne = MathExpression.newBuilder().setGroup(expression).build() + val groupTwo = MathExpression.newBuilder().setGroup(groupOne).build() + val error = MultipleRedundantParenthesesError("((5))", groupTwo) + + assertThat(error).isMultipleRedundantParenthesesThat().apply { + hasRawExpressionThat().isEqualTo("((5))") + hasExpressionThat().hasStructureThatMatches { + group { + group { + constant { + hasExpressionThat().evaluatesToIntegerThat().isEqualTo(5) + } + } + } + } + } + } + + @Test + fun testMathParsingErrorSubject_matchesUnnecessarySymbol() { + val error = UnnecessarySymbolsError("@") + assertThat(error).isUnnecessarySymbolWithSymbolThat().isEqualTo("@") + } + + @Test + fun testMathParsingErrorSubject_matchesUnnecessarySymbol_fails() { + val error = UnnecessarySymbolsError("@") + assertThrows(AssertionError::class.java) { + assertThat(error).isUnnecessarySymbolWithSymbolThat().isEqualTo("#") + } + } + + @Test + fun testMathParsingErrorSubject_isNumberAfterVariableError() { + val number = Real.newBuilder().setInteger(5).build() + val error = NumberAfterVariableError(number, "x") + + assertThat(error).isNumberAfterVariableThat().apply { + hasNumberThat().isIntegerThat().isEqualTo(5) + hasVariableThat().isEqualTo("x") + } + } + + @Test + fun testMathParsingErrorSubject_isNumberAfterVariableError_fails() { + val number = Real.newBuilder().setInteger(5).build() + val error = NumberAfterVariableError(number, "x") + assertThrows(AssertionError::class.java) { + assertThat(error).isNumberAfterVariableThat().apply { + hasNumberThat().isIntegerThat().isEqualTo(5) + hasVariableThat().isEqualTo("y") + } + } + } + + @Test + fun testMathParsingErrorSubject_isSubsequentBinaryOperatorsError() { + val error = SubsequentBinaryOperatorsError("x", "+") + assertThat(error).isSubsequentBinaryOperatorsThat().apply { + hasFirstOperatorThat().isEqualTo("x") + hasSecondOperatorThat().isEqualTo("+") + } + } + + @Test + fun testMathParsingErrorSubject_isSubsequentBinaryOperatorsError_fails() { + val error = SubsequentBinaryOperatorsError("x", "+") + assertThrows(AssertionError::class.java) { + assertThat(error).isSubsequentBinaryOperatorsThat().apply { + hasFirstOperatorThat().isEqualTo("y") + hasSecondOperatorThat().isEqualTo("-") + } + } + } + + @Test + fun testMathParsingErrorSubject_isSubsequentUnaryOperatorsError() { + val error = SubsequentUnaryOperatorsError + assertThat(error).isSubsequentUnaryOperators() + } + + @Test + fun testMathParsingErrorSubject_isNoVarOrNumBeforeBinaryOperator() { + val operator = MathBinaryOperation.Operator.ADD + val error = NoVariableOrNumberBeforeBinaryOperatorError(operator, "+") + assertThat(error).isNoVarOrNumBeforeBinaryOperatorThat().apply { + hasOperatorThat().isEqualTo(operator) + hasOperatorSymbolThat().isEqualTo("+") + } + } + + @Test + fun testMathParsingErrorSubject_isNoVarOrNumBeforeBinaryOperator_fails() { + val operator = MathBinaryOperation.Operator.ADD + val error = NoVariableOrNumberBeforeBinaryOperatorError(operator, "+") + assertThrows(AssertionError::class.java) { + assertThat(error).isNoVarOrNumBeforeBinaryOperatorThat().apply { + hasOperatorThat().isEqualTo(MathBinaryOperation.Operator.SUBTRACT) + hasOperatorSymbolThat().isEqualTo("-") + } + } + } + + @Test + fun testMathParsingErrorSubject_isNoVariableOrNumberAfterBinaryOperator() { + val operator = MathBinaryOperation.Operator.ADD + val error = NoVariableOrNumberAfterBinaryOperatorError(operator, "+") + assertThat(error).isNoVariableOrNumberAfterBinaryOperatorThat().apply { + hasOperatorThat().isEqualTo(operator) + hasOperatorSymbolThat().isEqualTo("+") + } + } + + @Test + fun testMathParsingErrorSubject_isNoVariableOrNumberAfterBinaryOperator_fails() { + val operator = MathBinaryOperation.Operator.ADD + val error = NoVariableOrNumberAfterBinaryOperatorError(operator, "+") + assertThrows(AssertionError::class.java) { + assertThat(error).isNoVariableOrNumberAfterBinaryOperatorThat().apply { + hasOperatorThat().isEqualTo(MathBinaryOperation.Operator.SUBTRACT) + hasOperatorSymbolThat().isEqualTo("-") + } + } + } + + @Test + fun testMathParsingErrorSubject_isExponentIsVariableExpressionError() { + val error = ExponentIsVariableExpressionError + assertThat(error).isExponentIsVariableExpression() + } + + @Test + fun testMathParsingErrorSubject_isExponentTooLargeError() { + val error = ExponentTooLargeError + assertThat(error).isExponentTooLarge() + } + + @Test + fun testMathParsingErrorSubject_isNestedExponentsError() { + val error = NestedExponentsError + assertThat(error).isNestedExponents() + } + + @Test + fun testMathParsingErrorSubject_isHangingSquareRootError() { + val error = HangingSquareRootError + assertThat(error).isHangingSquareRoot() + } + + @Test + fun testMathParsingErrorSubject_isTermDividedByZeroError() { + val error = TermDividedByZeroError + assertThat(error).isTermDividedByZero() + } + + @Test + fun testMathParsingErrorSubject_isVariableInNumericExpressionError() { + val error = VariableInNumericExpressionError + assertThat(error).isVariableInNumericExpression() + } + + @Test + fun testMathParsingErrorSubject_isDisabledVariablesInUseWithVariablesError() { + val error = DisabledVariablesInUseError(listOf("x", "y")) + assertThat(error).isDisabledVariablesInUseWithVariablesThat().containsExactly("x", "y") + } + + @Test + fun testMathParsingErrorSubject_isDisabledVariablesInUseWithVariablesError_fails() { + val error = DisabledVariablesInUseError(listOf("x", "y")) + assertThrows(AssertionError::class.java) { + assertThat(error).isDisabledVariablesInUseWithVariablesThat().containsExactly("x", "z") + } + } + + @Test + fun testMathParsingErrorSubject_isEquationIsMissingEqualsError() { + val error = EquationIsMissingEqualsError + assertThat(error).isEquationIsMissingEquals() + } + + @Test + fun testMathParsingErrorSubject_isEquationHasTooManyEqualsError() { + val error = EquationHasTooManyEqualsError + assertThat(error).isEquationHasTooManyEquals() + } + + @Test + fun testMathParsingErrorSubject_isEquationMissingLhsOrRhsError() { + val error = EquationMissingLhsOrRhsError + assertThat(error).isEquationMissingLhsOrRhs() + } + + @Test + fun testMathParsingErrorSubject_isInvalidFunctionInUseWithNameError() { + val error = InvalidFunctionInUseError("sin") + assertThat(error).isInvalidFunctionInUseWithNameThat().isEqualTo("sin") + } + + @Test + fun testMathParsingErrorSubject_isFunctionNameIncompleteError() { + val error = FunctionNameIncompleteError + assertThat(error).isFunctionNameIncomplete() + } + + @Test + fun testMathParsingErrorSubject_isGenericError() { + val error = GenericError + assertThat(error).isGenericError() + } +}