diff --git a/test/fixtures/comments.sb3 b/test/fixtures/comments.sb3
new file mode 100644
index 000000000..ce937c454
Binary files /dev/null and b/test/fixtures/comments.sb3 differ
diff --git a/test/integration/comments_sb3.js b/test/integration/comments_sb3.js
new file mode 100644
index 000000000..fd3766622
--- /dev/null
+++ b/test/integration/comments_sb3.js
@@ -0,0 +1,91 @@
+const path = require('path');
+const test = require('tap').test;
+const makeTestStorage = require('../fixtures/make-test-storage');
+const readFileToBuffer = require('../fixtures/readProjectFile').readFileToBuffer;
+const VirtualMachine = require('../../src/index');
+
+const projectUri = path.resolve(__dirname, '../fixtures/comments.sb3');
+const project = readFileToBuffer(projectUri);
+
+test('load an sb3 project with comments', t => {
+    const vm = new VirtualMachine();
+    vm.attachStorage(makeTestStorage());
+
+    // Evaluate playground data and exit
+    vm.on('playgroundData', e => {
+        const threads = JSON.parse(e.threads);
+        t.equal(threads.length, 0);
+
+        const stage = vm.runtime.targets[0];
+        const target = vm.runtime.targets[1];
+
+        const stageComments = Object.values(stage.comments);
+
+        // Stage has 1 comment, and it is minimized.
+        t.equal(stageComments.length, 1);
+        t.equal(stageComments[0].minimized, true);
+        t.equal(stageComments[0].text, 'A minimized stage comment.');
+        // The stage comment is a workspace comment
+        t.equal(stageComments[0].blockId, null);
+
+        // Sprite 1 has 6 Comments, 1 workspace comment, and 5 block comments
+        const targetComments = Object.values(target.comments);
+        t.equal(targetComments.length, 6);
+        const spriteWorkspaceComments = targetComments.filter(comment => comment.blockId === null);
+        t.equal(spriteWorkspaceComments.length, 1);
+        t.equal(spriteWorkspaceComments[0].minimized, false);
+        t.equal(spriteWorkspaceComments[0].text, 'This is a workspace comment.');
+
+        // Test the sprite block comments
+        const blockComments = targetComments.filter(comment => !!comment.blockId);
+        t.equal(blockComments.length, 5);
+
+        t.equal(blockComments[0].minimized, true);
+        t.equal(blockComments[0].text, '1. Green Flag Comment.');
+        const greenFlagBlock = target.blocks.getBlock(blockComments[0].blockId);
+        t.equal(greenFlagBlock.comment, blockComments[0].id);
+        t.equal(greenFlagBlock.opcode, 'event_whenflagclicked');
+
+        t.equal(blockComments[1].minimized, true);
+        t.equal(blockComments[1].text, '2. Turn 15 Degrees Comment.');
+        const turnRightBlock = target.blocks.getBlock(blockComments[1].blockId);
+        t.equal(turnRightBlock.comment, blockComments[1].id);
+        t.equal(turnRightBlock.opcode, 'motion_turnright');
+
+        t.equal(blockComments[2].minimized, false);
+        t.equal(blockComments[2].text, '3. Comment for a loop.');
+        const repeatBlock = target.blocks.getBlock(blockComments[2].blockId);
+        t.equal(repeatBlock.comment, blockComments[2].id);
+        t.equal(repeatBlock.opcode, 'control_repeat');
+
+        t.equal(blockComments[3].minimized, false);
+        t.equal(blockComments[3].text, '4. Comment for a block nested in a loop.');
+        const changeColorBlock = target.blocks.getBlock(blockComments[3].blockId);
+        t.equal(changeColorBlock.comment, blockComments[3].id);
+        t.equal(changeColorBlock.opcode, 'looks_changeeffectby');
+
+        t.equal(blockComments[4].minimized, false);
+        t.equal(blockComments[4].text, '5. Comment for a block outside of a loop.');
+        const stopAllBlock = target.blocks.getBlock(blockComments[4].blockId);
+        t.equal(stopAllBlock.comment, blockComments[4].id);
+        t.equal(stopAllBlock.opcode, 'control_stop');
+
+        t.end();
+        process.nextTick(process.exit);
+    });
+
+    // Start VM, load project, and run
+    t.doesNotThrow(() => {
+        vm.start();
+        vm.clear();
+        vm.setCompatibilityMode(false);
+        vm.setTurboMode(false);
+        vm.loadProject(project).then(() => {
+            vm.greenFlag();
+            setTimeout(() => {
+                vm.getPlaygroundData();
+                vm.stopAll();
+            }, 100);
+        });
+    });
+});
diff --git a/test/unit/serialization_sb3.js b/test/unit/serialization_sb3.js
index a3be33a7a..4b7723151 100644
--- a/test/unit/serialization_sb3.js
+++ b/test/unit/serialization_sb3.js
@@ -3,11 +3,12 @@ const path = require('path');
 const VirtualMachine = require('../../src/index');
 const sb3 = require('../../src/serialization/sb3');
 const readFileToBuffer = require('../fixtures/readProjectFile').readFileToBuffer;
-const projectPath = path.resolve(__dirname, '../fixtures/clone-cleanup.sb2');
+const exampleProjectPath = path.resolve(__dirname, '../fixtures/clone-cleanup.sb2');
+const commentsSB2ProjectPath = path.resolve(__dirname, '../fixtures/comments.sb2');
 
 test('serialize', t => {
     const vm = new VirtualMachine();
-    vm.loadProject(readFileToBuffer(projectPath))
+    vm.loadProject(readFileToBuffer(exampleProjectPath))
         .then(() => {
             const result = sb3.serialize(vm.runtime);
             // @todo Analyze
@@ -24,3 +25,44 @@ test('deserialize', t => {
         t.end();
     });
 });
+
+
+test('serialize sb2 project with comments as sb3', t => {
+    const vm = new VirtualMachine();
+    vm.loadProject(readFileToBuffer(commentsSB2ProjectPath))
+        .then(() => {
+            const result = sb3.serialize(vm.runtime);
+
+            t.type(JSON.stringify(result), 'string');
+            t.type(result.targets, 'object');
+            t.equal(Array.isArray(result.targets), true);
+            t.equal(result.targets.length, 2);
+
+            const stage = result.targets[0];
+            t.equal(stage.isStage, true);
+            // The stage has 0 blocks, and 1 workspace comment
+            t.type(stage.blocks, 'object');
+            t.equal(Object.keys(stage.blocks).length, 0);
+            t.type(stage.comments, 'object');
+            t.equal(Object.keys(stage.comments).length, 1);
+            const stageBlockComments = Object.values(stage.comments).filter(comment => !!comment.blockId);
+            const stageWorkspaceComments = Object.values(stage.comments).filter(comment => comment.blockId === null);
+            t.equal(stageBlockComments.length, 0);
+            t.equal(stageWorkspaceComments.length, 1);
+
+            const sprite = result.targets[1];
+            t.equal(sprite.isStage, false);
+            t.type(sprite.blocks, 'object');
+            // Sprite 1 has 6 blocks, 5 block comments, and 1 workspace comment
+            t.equal(Object.keys(sprite.blocks).length, 6);
+            t.type(sprite.comments, 'object');
+            t.equal(Object.keys(sprite.comments).length, 6);
+
+            const spriteBlockComments = Object.values(sprite.comments).filter(comment => !!comment.blockId);
+            const spriteWorkspaceComments = Object.values(sprite.comments).filter(comment => comment.blockId === null);
+            t.equal(spriteBlockComments.length, 5);
+            t.equal(spriteWorkspaceComments.length, 1);
+
+            t.end();
+        });
+});