tests: pdf parser test based on prepared files
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
package agzam.vyatsu.data.remote.pdf
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class PdfDumpTest {
|
||||
|
||||
@Test
|
||||
fun dumpParsedSchedule() {
|
||||
val instrumentation = InstrumentationRegistry.getInstrumentation()
|
||||
val bytes = instrumentation.context.assets.open("schedule.pdf").use { it.readBytes() }
|
||||
|
||||
val days = PdfScheduleParser.parse(bytes)
|
||||
|
||||
val target = instrumentation.targetContext.getExternalFilesDir(null)!!.resolve("parsed.txt")
|
||||
target.writeText(days.joinToString(separator = "\n"))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
package agzam.vyatsu.data.remote.pdf
|
||||
|
||||
import agzam.vyatsu.domain.model.Day
|
||||
import agzam.vyatsu.domain.model.Lesson
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalTime
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class PdfScheduleParserTest {
|
||||
|
||||
companion object {
|
||||
private val days: List<Day> by lazy {
|
||||
val bytes = InstrumentationRegistry.getInstrumentation().context.assets
|
||||
.open("schedule.pdf")
|
||||
.use { it.readBytes() }
|
||||
PdfScheduleParser.parse(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
private fun day(date: String): Day = days.first { it.date == LocalDate.parse(date) }
|
||||
|
||||
private fun lessons(date: String, start: String): List<Lesson> =
|
||||
day(date).intervals
|
||||
.first { it.start == LocalTime.parse(start) }
|
||||
.lessons
|
||||
.filter { it.raw.isNotBlank() }
|
||||
|
||||
private fun allLessons(date: String): List<Lesson> =
|
||||
day(date).intervals.flatMap { it.lessons }.filter { it.raw.isNotBlank() }
|
||||
|
||||
private fun Lesson.canonical(): String =
|
||||
listOf(subject, type.name, room, teacher, subgroup).joinToString("|")
|
||||
|
||||
@Test
|
||||
fun parsesWholeTwoWeekPeriod() {
|
||||
val expectedDates = (0..13L).map { LocalDate.of(2026, 9, 14).plusDays(it) }
|
||||
|
||||
assertEquals(expectedDates, days.map { it.date })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun everyDayHasSevenStandardIntervals() {
|
||||
val expectedTimes = listOf(
|
||||
LocalTime.of(8, 20) to LocalTime.of(9, 50),
|
||||
LocalTime.of(10, 0) to LocalTime.of(11, 30),
|
||||
LocalTime.of(11, 45) to LocalTime.of(13, 15),
|
||||
LocalTime.of(14, 0) to LocalTime.of(15, 30),
|
||||
LocalTime.of(15, 45) to LocalTime.of(17, 15),
|
||||
LocalTime.of(17, 20) to LocalTime.of(18, 50),
|
||||
LocalTime.of(18, 55) to LocalTime.of(20, 25)
|
||||
)
|
||||
|
||||
for (day in days) {
|
||||
assertEquals(day.date.toString(), expectedTimes, day.intervals.map { it.start to it.end })
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun emptyDaysHaveNoLessons() {
|
||||
val emptyDays = listOf("2026-09-14", "2026-09-19", "2026-09-20", "2026-09-26", "2026-09-27")
|
||||
|
||||
for (date in emptyDays) {
|
||||
assertEquals(date, emptyList<Lesson>(), allLessons(date))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesTwoLecturesInOneSlot() {
|
||||
assertEquals(
|
||||
listOf(
|
||||
"Объектно-ориентированный анализ и проектирование|LECTURE|2-202|Преподаватель -.П.|null",
|
||||
"Разработка Web-приложений|LECTURE|1-236|Преподаватель -.П.|null"
|
||||
),
|
||||
lessons("2026-09-15", "10:00").map { it.canonical() }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesThreeLecturesInOneSlot() {
|
||||
assertEquals(
|
||||
listOf(
|
||||
"Инструментальные средства проектирования компонентов вычислительной техники|LECTURE|2-201|Семеновых В.И.|null",
|
||||
"Предметно-ориентированные автоматизированные информационные системы|LECTURE|1-313|Прозорова Ю.А.|null",
|
||||
"Сценарное и функциональное программирование|LECTURE|1-311|Преподаватель -.П.|null"
|
||||
),
|
||||
lessons("2026-09-15", "11:45").map { it.canonical() }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesLaboratoryWork() {
|
||||
assertEquals(
|
||||
listOf(
|
||||
"Инструментальные средства проектирования компонентов вычислительной техники|LABORATORY|2-201|Семеновых В.И.|null",
|
||||
"Предметно-ориентированные автоматизированные информационные системы|LABORATORY|1-236|Прозорова Ю.А.|null",
|
||||
"Сценарное и функциональное программирование|LABORATORY|1-114|Преподаватель -.П.|null"
|
||||
),
|
||||
lessons("2026-09-15", "14:00").map { it.canonical() }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesWednesdayLectures() {
|
||||
assertEquals(
|
||||
listOf("Введение в архитектуру ЭВМ|LECTURE|1-242|Страбыкин Д.А.|null"),
|
||||
lessons("2026-09-16", "08:20").map { it.canonical() }
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Теория компиляторов и формальные грамматики|LECTURE|1-242|Мельцов В.Ю.|null"),
|
||||
lessons("2026-09-16", "10:00").map { it.canonical() }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesPhysicalEducationSubgroups() {
|
||||
val parsed = lessons("2026-09-17", "11:45").filter { it.room != null }
|
||||
|
||||
assertEquals(
|
||||
listOf(
|
||||
"Элективные дисциплины (модули) по физической культуре и спорту|PRACTICE|9-115|Трушкова Е.Л.|01 подгруппа",
|
||||
"Элективные дисциплины (модули) по физической культуре и спорту|PRACTICE|9-301|Салопин О.М.|01 подгруппа",
|
||||
"Элективные дисциплины (модули) по физической культуре и спорту|PRACTICE|9-301|Салопин О.М.|02 подгруппа"
|
||||
),
|
||||
parsed.map { it.canonical() }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun keepsRawTextWhenRoomHasTrailingPunctuation() {
|
||||
val unparsed = lessons("2026-09-17", "11:45").filter { it.room == null }
|
||||
|
||||
assertEquals(2, unparsed.size)
|
||||
assertTrue(unparsed.any { it.raw.contains("9-209.") })
|
||||
assertTrue(unparsed.any { it.raw.contains("9-208__") })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesFridaySubgroupLaboratories() {
|
||||
assertEquals(
|
||||
listOf(
|
||||
"Введение в архитектуру ЭВМ|LABORATORY|1-117|Страбыкин Д.А.|01 подгруппа",
|
||||
"Введение в архитектуру ЭВМ|LABORATORY|1-117_|Страбыкин Д.А.|02 подгруппа"
|
||||
),
|
||||
lessons("2026-09-18", "08:20").map { it.canonical() }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesSecondWeekMondayLaboratories() {
|
||||
assertEquals(
|
||||
listOf(
|
||||
"Теория компиляторов и формальные грамматики|LABORATORY|2-308|Караваева О.В.|01 подгруппа",
|
||||
"Теория компиляторов и формальные грамматики|LABORATORY|2-308_|Караваева О.В.|02 подгруппа"
|
||||
),
|
||||
lessons("2026-09-21", "10:00").map { it.canonical() }
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user