Merge pull request #451 from realm/sk-test-improvements

Improve JS tests
This commit is contained in:
Scott Kyle 2016-05-27 13:56:49 -07:00
commit b3ec066d12
17 changed files with 164 additions and 1886 deletions

View File

@ -55,9 +55,9 @@
"xcode": "0.8.4" "xcode": "0.8.4"
}, },
"devDependencies": { "devDependencies": {
"babel-eslint": "^6.0.0-beta.6", "babel-eslint": "^6.0.4",
"eslint": "^2.4.0", "eslint": "^2.10.2",
"eslint-plugin-react": "^4.2.3", "eslint-plugin-react": "^5.1.1",
"jsdoc": "^3.4.0", "jsdoc": "^3.4.0",
"semver": "^5.1.0" "semver": "^5.1.0"
}, },

View File

@ -182,15 +182,18 @@ RPCServer::RPCServer() {
return json::object(); return json::object();
}; };
m_requests["/clear_test_state"] = [this](const json dict) { m_requests["/clear_test_state"] = [this](const json dict) {
for (auto object : m_objects) { // The session ID points to the Realm constructor object, which should remain.
// The session ID points to the Realm constructor object, which should remain. auto realm_constructor = m_objects[m_session_id];
if (object.first != m_session_id) { m_objects.clear();
m_objects.erase(object.first);
} if (realm_constructor) {
m_objects.emplace(m_session_id, realm_constructor);
} }
m_callbacks.clear(); m_callbacks.clear();
JSGarbageCollect(m_context); JSGarbageCollect(m_context);
js::delete_all_realms(); js::delete_all_realms();
return json::object(); return json::object();
}; };
} }

View File

@ -14,8 +14,5 @@
"Uint32Array": false, "Uint32Array": false,
"Uint8Array": false, "Uint8Array": false,
"Uint8ClampedArray": false "Uint8ClampedArray": false
},
"rules": {
"no-redeclare": 1
} }
} }

View File

@ -1,36 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
'use strict';
var Realm = require('realm');
var prototype = exports.prototype = {};
exports.extend = function(object) {
object.__proto__ = prototype;
return object;
};
Object.defineProperties(prototype, {
afterEach: {
value: function() {
Realm.clearTestState();
}
}
});

View File

@ -19,11 +19,10 @@
'use strict'; 'use strict';
var Realm = require('realm'); var Realm = require('realm');
var BaseTest = require('./base-test');
var TestCase = require('./asserts'); var TestCase = require('./asserts');
var Schemas = require('./schemas'); var Schemas = require('./schemas');
module.exports = BaseTest.extend({ module.exports = {
testEncryptedInvalidKeys: function() { testEncryptedInvalidKeys: function() {
// test failure with invalid keys // test failure with invalid keys
TestCase.assertThrows(function() { TestCase.assertThrows(function() {
@ -54,7 +53,7 @@ module.exports = BaseTest.extend({
}); });
// test can reopen with original key // test can reopen with original key
var realm = new Realm({schema: [Schemas.TestObject], encryptionKey: key}); realm = new Realm({schema: [Schemas.TestObject], encryptionKey: key});
TestCase.assertEqual(realm.objects('TestObject').length, 1); TestCase.assertEqual(realm.objects('TestObject').length, 1);
}, },
}); };

View File

@ -18,6 +18,8 @@
'use strict'; 'use strict';
var Realm = require('realm');
var TESTS = { var TESTS = {
ListTests: require('./list-tests'), ListTests: require('./list-tests'),
ObjectTests: require('./object-tests'), ObjectTests: require('./object-tests'),
@ -58,7 +60,14 @@ exports.runTest = function(suiteName, testName) {
var testMethod = testSuite && testSuite[testName]; var testMethod = testSuite && testSuite[testName];
if (testMethod) { if (testMethod) {
testMethod.call(testSuite); // Start fresh in case of a crash in a previous run.
Realm.clearTestState();
try {
testMethod.call(testSuite);
} finally {
Realm.clearTestState();
}
} else if (!testSuite || !(testName in SPECIAL_METHODS)) { } else if (!testSuite || !(testName in SPECIAL_METHODS)) {
throw new Error('Missing test: ' + suiteName + '.' + testName); throw new Error('Missing test: ' + suiteName + '.' + testName);
} }

View File

@ -19,11 +19,10 @@
'use strict'; 'use strict';
var Realm = require('realm'); var Realm = require('realm');
var BaseTest = require('./base-test');
var TestCase = require('./asserts'); var TestCase = require('./asserts');
var schemas = require('./schemas'); var schemas = require('./schemas');
module.exports = BaseTest.extend({ module.exports = {
testListConstructor: function() { testListConstructor: function() {
var realm = new Realm({schema: [schemas.PersonObject, schemas.PersonList]}); var realm = new Realm({schema: [schemas.PersonObject, schemas.PersonList]});
@ -527,7 +526,7 @@ module.exports = BaseTest.extend({
list = object.list; list = object.list;
}); });
var names = function(results, prop) { var names = function(results) {
return results.map(function(object) { return results.map(function(object) {
return object.name; return object.name;
}); });
@ -653,4 +652,4 @@ module.exports = BaseTest.extend({
list.length; list.length;
}); });
}, },
}); };

View File

@ -19,11 +19,10 @@
'use strict'; 'use strict';
var Realm = require('realm'); var Realm = require('realm');
var BaseTest = require('./base-test');
var TestCase = require('./asserts'); var TestCase = require('./asserts');
var Schemas = require('./schemas'); var Schemas = require('./schemas');
module.exports = BaseTest.extend({ module.exports = {
testMigrationFunction: function() { testMigrationFunction: function() {
var count = 0; var count = 0;
function migrationFunction(oldRealm, newRealm) { function migrationFunction(oldRealm, newRealm) {
@ -82,7 +81,7 @@ module.exports = BaseTest.extend({
}); });
realm.close(); realm.close();
var realm = new Realm({ realm = new Realm({
schema: [{ schema: [{
name: 'TestObject', name: 'TestObject',
properties: { properties: {
@ -130,7 +129,7 @@ module.exports = BaseTest.extend({
}]}); }]});
realm.close(); realm.close();
var realm = new Realm({ realm = new Realm({
schema: [{ schema: [{
name: 'TestObject', name: 'TestObject',
properties: { properties: {
@ -159,4 +158,4 @@ module.exports = BaseTest.extend({
} }
}); });
}, },
}); };

View File

@ -19,7 +19,6 @@
'use strict'; 'use strict';
var Realm = require('realm'); var Realm = require('realm');
var BaseTest = require('./base-test');
var TestCase = require('./asserts'); var TestCase = require('./asserts');
var schemas = require('./schemas'); var schemas = require('./schemas');
@ -28,7 +27,7 @@ var RANDOM_DATA = new Uint8Array([
0x67, 0x1e, 0x40, 0xa7, 0x6d, 0x52, 0x83, 0xda, 0x07, 0x29, 0x9c, 0x70, 0x38, 0x48, 0x4e, 0xff, 0x67, 0x1e, 0x40, 0xa7, 0x6d, 0x52, 0x83, 0xda, 0x07, 0x29, 0x9c, 0x70, 0x38, 0x48, 0x4e, 0xff,
]); ]);
module.exports = BaseTest.extend({ module.exports = {
testBasicTypesPropertyGetters: function() { testBasicTypesPropertyGetters: function() {
var realm = new Realm({schema: [schemas.BasicTypes]}); var realm = new Realm({schema: [schemas.BasicTypes]});
var object; var object;
@ -506,4 +505,4 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(realm.objects('Date')[2].currentDate.getTime(), 1000000000000); TestCase.assertEqual(realm.objects('Date')[2].currentDate.getTime(), 1000000000000);
TestCase.assertEqual(realm.objects('Date')[3].currentDate.getTime(), -1000000000000); TestCase.assertEqual(realm.objects('Date')[3].currentDate.getTime(), -1000000000000);
} }
}); };

File diff suppressed because it is too large Load Diff

View File

@ -19,11 +19,10 @@
'use strict'; 'use strict';
var Realm = require('realm'); var Realm = require('realm');
var BaseTest = require('./base-test');
var TestCase = require('./asserts'); var TestCase = require('./asserts');
var schemas = require('./schemas'); var schemas = require('./schemas');
module.exports = BaseTest.extend({ module.exports = {
testRealmConstructor: function() { testRealmConstructor: function() {
var realm = new Realm({schema: []}); var realm = new Realm({schema: []});
TestCase.assertTrue(realm instanceof Realm); TestCase.assertTrue(realm instanceof Realm);
@ -160,13 +159,16 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(Realm.schemaVersion(Realm.defaultPath), -1); TestCase.assertEqual(Realm.schemaVersion(Realm.defaultPath), -1);
var realm = new Realm({schema: []}); var realm = new Realm({schema: []});
TestCase.assertEqual(realm.schemaVersion, 0);
TestCase.assertEqual(Realm.schemaVersion(Realm.defaultPath), 0); TestCase.assertEqual(Realm.schemaVersion(Realm.defaultPath), 0);
realm = new Realm({schema: [], schemaVersion: 2, path: 'another.realm'}); realm = new Realm({schema: [], schemaVersion: 2, path: 'another.realm'});
TestCase.assertEqual(realm.schemaVersion, 2);
TestCase.assertEqual(Realm.schemaVersion('another.realm'), 2); TestCase.assertEqual(Realm.schemaVersion('another.realm'), 2);
var encryptionKey = new Int8Array(64); var encryptionKey = new Int8Array(64);
realm = new Realm({schema: [], schemaVersion: 3, path: 'encrypted.realm', encryptionKey: encryptionKey}); realm = new Realm({schema: [], schemaVersion: 3, path: 'encrypted.realm', encryptionKey: encryptionKey});
TestCase.assertEqual(realm.schemaVersion, 3);
TestCase.assertEqual(Realm.schemaVersion('encrypted.realm', encryptionKey), 3); TestCase.assertEqual(Realm.schemaVersion('encrypted.realm', encryptionKey), 3);
TestCase.assertThrows(function() { TestCase.assertThrows(function() {
@ -652,7 +654,7 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(notificationName, 'change'); TestCase.assertEqual(notificationName, 'change');
var secondNotificationCount = 0; var secondNotificationCount = 0;
function secondNotification(realm, name) { function secondNotification() {
secondNotificationCount++; secondNotificationCount++;
} }
@ -750,7 +752,7 @@ module.exports = BaseTest.extend({
// copy should not overwrite existing files // copy should not overwrite existing files
Realm.copyBundledRealmFiles(); Realm.copyBundledRealmFiles();
var realm = new Realm({path: 'dates-v5.realm', schema: [schemas.DateObject]}); realm = new Realm({path: 'dates-v5.realm', schema: [schemas.DateObject]});
TestCase.assertEqual(realm.objects('Date')[0].currentDate.getTime(), 1); TestCase.assertEqual(realm.objects('Date')[0].currentDate.getTime(), 1);
}, },
}); };

View File

@ -19,11 +19,10 @@
'use strict'; 'use strict';
var Realm = require('realm'); var Realm = require('realm');
var BaseTest = require('./base-test');
var TestCase = require('./asserts'); var TestCase = require('./asserts');
var schemas = require('./schemas'); var schemas = require('./schemas');
module.exports = BaseTest.extend({ module.exports = {
testResultsConstructor: function() { testResultsConstructor: function() {
var realm = new Realm({schema: [schemas.TestObject]}); var realm = new Realm({schema: [schemas.TestObject]});
var objects = realm.objects('TestObject'); var objects = realm.objects('TestObject');
@ -100,15 +99,16 @@ module.exports = BaseTest.extend({
testResultsInvalidObjectType: function() { testResultsInvalidObjectType: function() {
var realm = new Realm({schema: [schemas.TestObject]}); var realm = new Realm({schema: [schemas.TestObject]});
TestCase.assertThrows(function() { TestCase.assertThrows(function() {
var objects = realm.objects('NotTestObject'); realm.objects('NotTestObject');
}); });
}, },
testResultsEnumerate: function() { testResultsEnumerate: function() {
var realm = new Realm({schema: [schemas.TestObject]}); var realm = new Realm({schema: [schemas.TestObject]});
var objects = realm.objects('TestObject'); var objects = realm.objects('TestObject');
var index;
for (var index in objects) { for (index in objects) {
TestCase.assertTrue(false, "No objects should have been enumerated"); TestCase.assertTrue(false, "No objects should have been enumerated");
} }
@ -119,7 +119,7 @@ module.exports = BaseTest.extend({
var count = 0; var count = 0;
var keys = Object.keys(objects); var keys = Object.keys(objects);
for (var index in objects) { for (index in objects) {
TestCase.assertEqual(count++, +index); TestCase.assertEqual(count++, +index);
TestCase.assertEqual(keys[index], index); TestCase.assertEqual(keys[index], index);
} }
@ -185,7 +185,7 @@ module.exports = BaseTest.extend({
realm.create('IntPrimaryObject', {primaryCol: 0, valueCol: 'c'}); realm.create('IntPrimaryObject', {primaryCol: 0, valueCol: 'c'});
}); });
var primaries = function(results, prop) { var primaries = function(results) {
return results.map(function(object) { return results.map(function(object) {
return object.primaryCol; return object.primaryCol;
}); });
@ -368,4 +368,4 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(snapshot.length, 0); TestCase.assertEqual(snapshot.length, 0);
}); });
} }
}); };

View File

@ -18,7 +18,6 @@
"parser": "babel-eslint", "parser": "babel-eslint",
"parserOptions": { "parserOptions": {
"ecmaFeatures": { "ecmaFeatures": {
"forOf": false,
"jsx": true "jsx": true
} }
}, },

View File

@ -17,60 +17,44 @@
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
'use strict'; 'use strict';
const React = require('react'); import {
const Realm = require('realm');
const RealmTests = require('realm-tests');
const builder = require('xmlbuilder');
const RNFS = require('react-native-fs');
const {
AppRegistry, AppRegistry,
StyleSheet, StyleSheet,
Image, Image,
Text, Text,
View, View,
TouchableNativeFeedback, } from 'react-native';
} = require('react-native');
RealmTests.registerTests({ import builder from 'xmlbuilder';
ListViewTest: require('./tests/listview-test'), import React from 'react';
}); import RNFS from 'react-native-fs';
import { getTestNames, runTest } from './tests';
function runTests() { async function runTests() {
let testNames = getTestNames();
let rootXml = builder.create('testsuites'); let rootXml = builder.create('testsuites');
let testNames = RealmTests.getTestNames();
for (let suiteName in testNames) { for (let suiteName in testNames) {
let itemTestsuite = rootXml.ele('testsuite'); let itemTestsuite = rootXml.ele('testsuite');
let nbrTests = 0; let nbrTests = 0;
let nbrFailures = 0; let nbrFailures = 0;
console.log('Starting suite ' + suiteName); console.log('Starting ' + suiteName);
testNames[suiteName].forEach((testName) => { for (let testName of testNames[suiteName]) {
nbrTests++; nbrTests++;
let itemTest = itemTestsuite.ele('testcase'); let itemTest = itemTestsuite.ele('testcase');
itemTest.att('name', testName); itemTest.att('name', testName);
console.log('Starting ' + testName);
RealmTests.runTest(suiteName, 'beforeEach');
try { try {
RealmTests.runTest(suiteName, testName); runTest(suiteName, testName);
console.log('+ ' + testName);
} }
catch (e) { catch (e) {
console.log('- ' + testName);
console.warn(e.message);
itemTest.ele('error', {'message': ''}, e.message); itemTest.ele('error', {'message': ''}, e.message);
nbrFailures++; nbrFailures++;
} }
finally { }
RealmTests.runTest(suiteName, 'afterEach');
}
});
// update Junit XML report // update Junit XML report
itemTestsuite.att('name', suiteName); itemTestsuite.att('name', suiteName);
@ -80,55 +64,57 @@ function runTests() {
} }
// export unit tests results // export unit tests results
var xmlString = rootXml.end({ pretty: true, indent: ' ', newline: '\n' }); let xmlString = rootXml.end({
var path = '/sdcard/tests.xml'; pretty: true,
indent: ' ',
newline: '\n',
});
// write the unit tests reports // write the unit tests reports
RNFS.writeFile(path, xmlString , 'utf8') try {
.then((success) => { await RNFS.writeFile('/sdcard/tests.xml', xmlString, 'utf8');
console.log('__REALM_REACT_ANDROID_TESTS_COMPLETED__'); console.log('__REALM_REACT_ANDROID_TESTS_COMPLETED__');
}) }
.catch((err) => { catch (e) {
console.log(err.message); console.error(e);
}); }
} }
class ReactTests extends React.Component { class ReactTests extends React.Component {
render() { render() {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text style={styles.button} onPress={runTests}> <Text style={styles.button} onPress={runTests}>
Running Tests... Running Tests...
</Text> </Text>
<Image <Image
style={styles.icon} style={styles.icon}
source={require('image!ic_launcher')} source={require('image!ic_launcher')}
onLoad={() => runTests()} onLoad={() => runTests()}
/> />
</View> </View>
); );
} }
} }
var styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
backgroundColor: '#F5FCFF', backgroundColor: '#F5FCFF',
}, },
welcome: { welcome: {
fontSize: 20, fontSize: 20,
textAlign: 'center', textAlign: 'center',
margin: 10, margin: 10,
}, },
instructions: { instructions: {
textAlign: 'center', textAlign: 'center',
color: '#333333', color: '#333333',
marginBottom: 5, marginBottom: 5,
}, },
}); });
AppRegistry.registerComponent('ReactTests', () => ReactTests); AppRegistry.registerComponent('ReactTests', () => ReactTests);

View File

@ -18,23 +18,21 @@
'use strict'; 'use strict';
const React = require('react'); import {
const Realm = require('realm');
const tests = require('./tests');
const {
AppRegistry, AppRegistry,
StyleSheet, StyleSheet,
Text, Text,
TouchableHighlight,
View, View,
} = require('react-native'); } from 'react-native';
import React from 'react';
import { runTests } from './tests';
class ReactTests extends React.Component { class ReactTests extends React.Component {
render() { render() {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text style={styles.button} onPress={tests.runTests}> <Text style={styles.button} onPress={runTests}>
Tap to Run Tests Tap to Run Tests
</Text> </Text>
<Text style={styles.instructions}> <Text style={styles.instructions}>
@ -46,7 +44,7 @@ class ReactTests extends React.Component {
} }
} }
var styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',

View File

@ -18,22 +18,14 @@
'use strict'; 'use strict';
const React = require('react-native'); import { NativeAppEventEmitter, NativeModules } from 'react-native';
const RealmTests = require('realm-tests'); import * as RealmTests from 'realm-tests';
import ListViewTest from './listview-test';
RealmTests.registerTests({ RealmTests.registerTests({
ListViewTest: require('./listview-test'), ListViewTest,
}); });
const {
NativeAppEventEmitter,
NativeModules,
} = React;
module.exports = {
runTests,
};
// Listen for event to run a particular test. // Listen for event to run a particular test.
NativeAppEventEmitter.addListener('realm-run-test', (test) => { NativeAppEventEmitter.addListener('realm-run-test', (test) => {
let error; let error;
@ -48,29 +40,41 @@ NativeAppEventEmitter.addListener('realm-run-test', (test) => {
// Inform the native test harness about the test suite once it's ready. // Inform the native test harness about the test suite once it's ready.
setTimeout(() => { setTimeout(() => {
NativeModules.Realm.emit('realm-test-names', RealmTests.getTestNames()); // The emit() method only exists on iOS, for now.
if (NativeModules.Realm.emit) {
NativeModules.Realm.emit('realm-test-names', getTestNames());
}
}, 0); }, 0);
function runTests() { export function getTestNames() {
let testNames = RealmTests.getTestNames(); return RealmTests.getTestNames();
}
export function runTests() {
let testNames = getTestNames();
for (let suiteName in testNames) { for (let suiteName in testNames) {
console.log('Starting ' + suiteName); console.log('Starting ' + suiteName);
for (let testName of testNames[suiteName]) { for (let testName of testNames[suiteName]) {
RealmTests.runTest(suiteName, 'beforeEach'); runTest(suiteName, testName);
try {
RealmTests.runTest(suiteName, testName);
console.log('+ ' + testName);
}
catch (e) {
console.warn('- ' + testName);
console.warn(e.message);
}
finally {
RealmTests.runTest(suiteName, 'afterEach');
}
} }
} }
} }
export function runTest(suiteName, testName) {
RealmTests.runTest(suiteName, 'beforeEach');
try {
RealmTests.runTest(suiteName, testName);
console.log('+ ' + testName);
}
catch (e) {
console.warn('- ' + testName);
console.warn(e.message || e);
throw e;
}
finally {
RealmTests.runTest(suiteName, 'afterEach');
}
}

View File

@ -18,9 +18,9 @@
'use strict'; 'use strict';
const Realm = require('realm'); import Realm from 'realm';
const { ListView } = require('realm/react-native'); import { ListView } from 'realm/react-native';
const { assertEqual, assertTrue } = require('realm-tests/asserts'); import { assertEqual, assertTrue } from 'realm-tests/asserts';
const OBJECT_SCHEMA = { const OBJECT_SCHEMA = {
name: 'UniqueObject', name: 'UniqueObject',
@ -48,11 +48,7 @@ function createDataSource() {
}); });
} }
module.exports = { export default {
afterEach() {
Realm.clearTestState();
},
testDataSource() { testDataSource() {
let realm = createRealm(); let realm = createRealm();
let objects = realm.objects('UniqueObject').sorted('id'); let objects = realm.objects('UniqueObject').sorted('id');