Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A preliminary unit test based on JSON unit tests #173

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .codespellrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[codespell]
skip = datasets,.git,*.pdf,*.svg,deprecated,*.xml,*.mediawiki,*.omn,datasets
ignore-words-list = covert,hed,recuse
ignore-words-list = covert,hed,recuse,afterAll
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ name: CI

on:
push:
branches: [master]
branches: '*'
pull_request:
branches: [master]
branches: '*'

jobs:
Build:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [18.x, 20.x, 21.x, 22.x]
node-version: [18.x, 22.x]

steps:
- name: Check out the code
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ node_modules
.idea
dist/
/venv/
spec_tests/
spec_tests/*.txt

# Unit test / coverage reports
htmlcov/
Expand Down
192 changes: 192 additions & 0 deletions spec_tests/jsonSpecificationTests.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import chai from 'chai'
const assert = chai.assert
import { beforeAll, describe, afterAll } from '@jest/globals'

import { buildSchemas } from '../validator/schema/init'

import { SchemaSpec, SchemasSpec } from '../common/schema/types'
import { parseHedStrings } from '../parser/main'
import { validateHedEventWithDefinitions } from '../validator/event/init'
import { BidsSidecar } from '../bids/types/json'
import { BidsTsvFile } from '../bids/types/tsv'
import BidsHedSidecarValidator from '../bids/validator/bidsHedSidecarValidator'
import BidsHedTsvValidator from '../bids/validator/bidsHedTsvValidator'
import { parseDefinitions } from '../validator/dataset'
const fs = require('fs')
const path = require('path')

const readFileSync = fs.readFileSync
let finalLog
let badLog
let testInfo
let schemaMap
let schemaSpecsMap

const test_file_name = 'nonschema_tests.json'

function defsToMap(defList) {
const defMap = {}

defList.forEach((str, index) => {
defMap[`def${index + 1}`] = str
})
if (defMap.size === 0) {
return {}
}
return { definitions: { HED: defMap } }
}

function tsvToString(events) {
return events.map((row) => row.join('\t')).join('\n')
}
function bidsIssuesToStr(issues) {
// Convert a list of issue dictionaries into a string of the hedCode keys.
return issues.map((issue) => issue.hedIssue.hedCode).join(', ')
}

function issuesToStr(issues) {
// Convert a list of issue dictionaries into a string of the hedCode keys.
return issues.map((dict) => dict.hedCode).join(', ')
}

const loadTestData = () => {
const testFile = path.join(__dirname, test_file_name)

// Read and parse the test file synchronously
const data = readFileSync(testFile, 'utf8')
testInfo = JSON.parse(data)
}

// Load data before defining the tests
loadTestData()

describe('HED', () => {
beforeAll(async () => {
jest.setTimeout(100000)
schemaSpecsMap = {}
schemaMap = {}
finalLog = ''
badLog = ''
await Promise.all(
testInfo.map(async (item) => {
if (!(item['schema'] in schemaSpecsMap)) {
const schemaFile = 'tests/data/HED' + item['schema'] + '.xml'
const schemaSpec = new SchemaSpec('', item['schema'], '', schemaFile)
const specs = new SchemasSpec().addSchemaSpec(schemaSpec)
schemaSpecsMap[item['schema']] = specs
schemaMap[item['schema']] = await buildSchemas(specs)
}
}),
)
finalLog = `Schemas: [ ${Object.keys(schemaMap).join(', ')} ]\n\n`
})

afterAll(() => {
const outlog = path.join(__dirname, 'test_log.txt')
fs.writeFileSync(outlog, finalLog, 'utf8')
const outbad = path.join(__dirname, 'test_badlog.txt')
fs.writeFileSync(outbad, badLog, 'utf8')
})

test('should load testInfo correctly', () => {
expect(testInfo).toBeDefined()
})

// Define dynamic tests
testInfo.forEach((info) => {
test(`Tests ${info['error_code']}: ${info['name']}`, () => {
finalLog = finalLog + `Running test for ${info['error_code']}: ${info['name']}\n`
const hedSchemas = schemaMap[info['schema']]
const [parsedDefStrings] = parseHedStrings(info['definitions'], hedSchemas)
const [definitions, definitionIssues] = parseDefinitions(parsedDefStrings)
expect(definitionIssues).toHaveLength(0)

const string_tests_passes = info['tests']['string_tests']['passes']
string_tests_passes.forEach((str, index) => {
const [valid_strings, string_passes_issues] = validateHedEventWithDefinitions(str, hedSchemas, definitions)

if (!valid_strings) {
badLog =
badLog +
`[${info['error_code']}: ${info['name']}]\n\tstr[${index}] ${str} should be valid by threw ${issuesToStr(string_passes_issues)}`
}
assert.strictEqual(valid_strings, true, `${str} should be valid`)
})

finalLog = finalLog + `\tValid string tests:\n\t\tpassed\n\tInvalid string tests:\n`

const string_tests_fails = info['tests']['string_tests']['fails']
string_tests_fails.forEach((str, index) => {
const [invalid_strings, string_fails_issues] = validateHedEventWithDefinitions(str, hedSchemas, definitions)
finalLog = finalLog + `\t\tstr[${index}] ${issuesToStr(string_fails_issues)}: ${str}\n`
assert.strictEqual(invalid_strings, false, `${str} should be invalid`)
})

/* const sidecar_tests_passes = info['tests']['sidecar_tests']['passes']
sidecar_tests_passes.forEach((sidecar, index) => {
const bidsSide = new BidsSidecar(`sidecar: ${index}`, sidecar, null)
const sideVal = new BidsHedSidecarValidator(bidsSide, hedSchemas)
const sidecarIssues = sideVal.validate()
expect(sidecarIssues).toHaveLength(0)
})
finalLog = finalLog + `\tValid sidecar tests:\n\t\tpassed\n\tInvalid sidecar tests:\n`

const sidecar_tests_fails = info['tests']['sidecar_tests']['fails']
sidecar_tests_fails.forEach((sidecar, index) => {
const bidsSide = new BidsSidecar(`sidecar: ${index}`, sidecar, null)
const sideVal = new BidsHedSidecarValidator(bidsSide, hedSchemas)
const sidecarIssues = sideVal.validate()
finalLog = finalLog + `\t\tsidecar[${index}] ${bidsIssuesToStr(sidecarIssues)} \n`
expect(sidecarIssues.length).toBeGreaterThan(0)
})

const event_tests_passes = info['tests']['event_tests']['passes']
event_tests_passes.forEach((events, index) => {
const eventString = tsvToString(events)
const defDict = defsToMap(info['definitions'])
const bidsTsv = new BidsTsvFile(`events: ${index}`, eventString, null, [], defDict)
const eventsVal = new BidsHedTsvValidator(bidsTsv, hedSchemas)
const eventsIssues = eventsVal.validate()
expect(eventsIssues).toHaveLength(0)
})
finalLog = finalLog + `\tValid events tests:\n\t\tpassed\n\tInvalid events tests:\n`

const event_tests_fails = info['tests']['event_tests']['fails']
event_tests_fails.forEach((events, index) => {
const eventString = tsvToString(events)
const defDict = defsToMap(info['definitions'])
const bidsTsv = new BidsTsvFile(`events: ${index}`, eventString, null, [], defDict)
const eventsVal = new BidsHedTsvValidator(bidsTsv, hedSchemas)
const eventsIssues = eventsVal.validate()
finalLog = finalLog + `\t\tevents[${index}] ${bidsIssuesToStr(eventsIssues)} \n`
expect(eventsIssues.length).toBeGreaterThan(0)
})

const combo_tests_passes = info['tests']['combo_tests']['passes']
combo_tests_passes.forEach((item, index) => {
const eventString = tsvToString(item['events'])
const defDict = defsToMap(info['definitions'])
const sidecarDict = item['sidecar']
const mergedJson = { ...sidecarDict, ...defDict }
const bidsTsv = new BidsTsvFile(`events: ${index}`, eventString, null, [], mergedJson)
const eventsVal = new BidsHedTsvValidator(bidsTsv, hedSchemas)
const eventsIssues = eventsVal.validate()
expect(eventsIssues).toHaveLength(0)
})
finalLog = finalLog + `\tValid combo tests:\n\t\tpassed\n\tInvalid combo tests:\n`

const combo_tests_fails = info['tests']['combo_tests']['fails']
combo_tests_fails.forEach((item, index) => {
const eventString = tsvToString(item['events'])
const defDict = defsToMap(info['definitions'])
const sidecarDict = item['sidecar']
const mergedJson = { ...sidecarDict, ...defDict }
const bidsTsv = new BidsTsvFile(`events: ${index}`, eventString, null, [], mergedJson)
const eventsVal = new BidsHedTsvValidator(bidsTsv, hedSchemas)
const eventsIssues = eventsVal.validate()
finalLog = finalLog + `\t\tevents[${index}] ${bidsIssuesToStr(eventsIssues)} \n`
expect(eventsIssues.length).toBeGreaterThan(0)
})*/
})
})
})
Loading
Loading