aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/__init__.py50
-rw-r--r--tests/test_classic_visualizer.py71
-rw-r--r--tests/test_commandline_parser.py21
-rw-r--r--tests/test_image_comp.py50
-rw-r--r--tests/test_mainwindow_undostack.py73
-rw-r--r--tests/test_text_comp.py32
-rw-r--r--tests/test_toolkit_common.py13
-rw-r--r--tests/test_toolkit_ffmpeg.py64
-rw-r--r--tests/test_toolkit_frame.py14
9 files changed, 364 insertions, 24 deletions
diff --git a/tests/__init__.py b/tests/__init__.py
index d0073ef..b615681 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -1,27 +1,39 @@
-import pytest
import os
-import sys
+import numpy
+
+# core always has to be imported first
+import avp.core
+from avp.toolkit.ffmpeg import readAudioFile
+from pytest import fixture
+
+
+@fixture
+def audioData():
+ """Fixture that gives a tuple of (completeAudioArray, duration)"""
+ soundFile = getTestDataPath("test.ogg")
+ yield readAudioFile(soundFile, MockVideoWorker())
def getTestDataPath(filename):
+ """Get path to a file in the ./data directory"""
tests_dir = os.path.dirname(os.path.abspath(__file__))
return os.path.join(tests_dir, "data", filename)
-def run(logFile):
- """Run Pytest, which then imports and runs all tests in this module."""
- os.environ["PYTEST_QT_API"] = "PyQt6"
- with open(logFile, "w") as f:
- # temporarily redirect stdout to a text file so we capture pytest's output
- sys.stdout = f
- try:
- val = pytest.main(
- [
- os.path.dirname(__file__),
- "-s", # disable pytest's internal capturing of stdout etc.
- ]
- )
- finally:
- sys.stdout = sys.__stdout__
-
- return val
+class MockSignal:
+ """Pretends to be a pyqtSignal"""
+
+ def emit(self, *args):
+ pass
+
+
+class MockVideoWorker:
+ """Pretends to be a video thread worker"""
+
+ progressBarSetText = MockSignal()
+ progressBarUpdate = MockSignal()
+
+
+def imageDataSum(image):
+ """Get sum of raw data of a Pillow Image object"""
+ return numpy.asarray(image, dtype="int32").sum(dtype="int32")
diff --git a/tests/test_classic_visualizer.py b/tests/test_classic_visualizer.py
new file mode 100644
index 0000000..e301263
--- /dev/null
+++ b/tests/test_classic_visualizer.py
@@ -0,0 +1,71 @@
+from avp.command import Command
+from pytestqt import qtbot
+from pytest import fixture
+from . import audioData, MockSignal, imageDataSum
+
+
+sampleSize = 1470 # 44100 / 30 = 1470
+
+
+@fixture
+def coreWithClassicComp(qtbot):
+ """Fixture providing a Command object with Classic Visualizer component added"""
+ command = Command()
+ command.core.insertComponent(
+ 0, command.core.moduleIndexFor("Classic Visualizer"), command
+ )
+ yield command.core
+
+
+def test_comp_classic_added(coreWithClassicComp):
+ """Add Classic Visualizer to core"""
+ assert len(coreWithClassicComp.selectedComponents) == 1
+
+
+def test_comp_classic_removed(coreWithClassicComp):
+ """Remove Classic Visualizer from core"""
+ coreWithClassicComp.removeComponent(0)
+ assert len(coreWithClassicComp.selectedComponents) == 0
+
+
+def test_comp_classic_drawBars(coreWithClassicComp, audioData):
+ """Call drawBars after creating audio spectrum data manually."""
+
+ spectrumArray = {
+ 0: coreWithClassicComp.selectedComponents[0].transformData(
+ 0, audioData[0], sampleSize, 0.08, 0.8, None, 20
+ )
+ }
+ for i in range(sampleSize, len(audioData[0]), sampleSize):
+ spectrumArray[i] = coreWithClassicComp.selectedComponents[0].transformData(
+ i,
+ audioData[0],
+ sampleSize,
+ 0.08,
+ 0.8,
+ spectrumArray[i - sampleSize].copy(),
+ 20,
+ )
+ image = coreWithClassicComp.selectedComponents[0].drawBars(
+ 1920, 1080, spectrumArray[sampleSize * 4], (0, 0, 0), 0
+ )
+ assert imageDataSum(image) == 37872316
+
+
+def test_comp_classic_drawBars_using_preFrameRender(coreWithClassicComp, audioData):
+ """Call drawBars after creating audio spectrum data using preFrameRender."""
+ comp = coreWithClassicComp.selectedComponents[0]
+ comp.preFrameRender(
+ completeAudioArray=audioData[0],
+ sampleSize=sampleSize,
+ progressBarSetText=MockSignal(),
+ progressBarUpdate=MockSignal(),
+ )
+ image = comp.drawBars(
+ 1920,
+ 1080,
+ coreWithClassicComp.selectedComponents[0].spectrumArray[sampleSize * 4],
+ (0, 0, 0),
+ 0,
+ )
+ assert imageDataSum(image) == 37872316
diff --git a/tests/test_commandline_parser.py b/tests/test_commandline_parser.py
index 8b07b8c..d092072 100644
--- a/tests/test_commandline_parser.py
+++ b/tests/test_commandline_parser.py
@@ -1,37 +1,38 @@
import sys
import pytest
from avp.command import Command
+from pytestqt import qtbot
-def test_commandline_help():
+def test_commandline_help(qtbot):
command = Command()
sys.argv = ["", "--help"]
with pytest.raises(SystemExit):
command.parseArgs()
-def test_commandline_help_if_bad_args():
+def test_commandline_help_if_bad_args(qtbot):
command = Command()
sys.argv = ["", "--junk"]
with pytest.raises(SystemExit):
command.parseArgs()
-def test_commandline_launches_gui_if_verbose():
+def test_commandline_launches_gui_if_verbose(qtbot):
command = Command()
sys.argv = ["", "--verbose"]
mode = command.parseArgs()
assert mode == "GUI"
-def test_commandline_launches_gui_if_verbose_with_project():
+def test_commandline_launches_gui_if_verbose_with_project(qtbot):
command = Command()
sys.argv = ["", "test", "--verbose"]
mode = command.parseArgs()
assert mode == "GUI"
-def test_commandline_tries_to_export():
+def test_commandline_tries_to_export(qtbot):
command = Command()
didCallFunction = False
@@ -43,3 +44,13 @@ def test_commandline_tries_to_export():
command.createAudioVisualization = captureFunction
command.parseArgs()
assert didCallFunction
+
+
+def test_commandline_parses_classic_by_alias(qtbot):
+ command = Command()
+ assert command.parseCompName("original") == "Classic Visualizer"
+
+
+def test_commandline_parses_conway_by_name(qtbot):
+ command = Command()
+ assert command.parseCompName("conway") == "Conway's Game of Life"
diff --git a/tests/test_image_comp.py b/tests/test_image_comp.py
new file mode 100644
index 0000000..a4f05e1
--- /dev/null
+++ b/tests/test_image_comp.py
@@ -0,0 +1,50 @@
+from avp.command import Command
+from pytestqt import qtbot
+from pytest import fixture
+from . import audioData, MockSignal, imageDataSum, getTestDataPath
+
+
+sampleSize = 1470 # 44100 / 30 = 1470
+
+
+@fixture
+def coreWithImageComp(qtbot):
+ """Fixture providing a Command object with Image component added"""
+ command = Command()
+ command.settings.setValue("outputHeight", 1080)
+ command.settings.setValue("outputWidth", 1920)
+ command.core.insertComponent(0, command.core.moduleIndexFor("Image"), command)
+ yield command.core
+
+
+def test_comp_image_set_path(coreWithImageComp):
+ "Set imagePath of Image component"
+ comp = coreWithImageComp.selectedComponents[0]
+ comp.imagePath = getTestDataPath("test.jpg")
+ image = comp.previewRender()
+ assert imageDataSum(image) == 463711601
+
+
+def test_comp_image_scale_50_1080p(coreWithImageComp):
+ """Image component stretches image to 50% at 1080p"""
+ comp = coreWithImageComp.selectedComponents[0]
+ comp.imagePath = getTestDataPath("test.jpg")
+ image = comp.previewRender()
+ sum = imageDataSum(image)
+ comp.page.spinBox_scale.setValue(50)
+ assert imageDataSum(comp.previewRender()) - sum / 4 < 2000
+
+
+def test_comp_image_scale_50_720p(coreWithImageComp):
+ """Image component stretches image to 50% at 720p"""
+ comp = coreWithImageComp.selectedComponents[0]
+ comp.imagePath = getTestDataPath("test.jpg")
+ comp.page.spinBox_scale.setValue(50)
+ image = comp.previewRender()
+ sum = imageDataSum(image)
+ comp.parent.settings.setValue("outputHeight", 720)
+ comp.parent.settings.setValue("outputWidth", 1280)
+ newImage = comp.previewRender()
+ assert image.width == 1920
+ assert newImage.width == 1280
+ assert imageDataSum(comp.previewRender()) == sum
diff --git a/tests/test_mainwindow_undostack.py b/tests/test_mainwindow_undostack.py
new file mode 100644
index 0000000..1eec1ef
--- /dev/null
+++ b/tests/test_mainwindow_undostack.py
@@ -0,0 +1,73 @@
+from pytest import fixture
+from pytestqt import qtbot
+from avp.gui.mainwindow import MainWindow
+from . import getTestDataPath
+
+
+@fixture
+def window(qtbot):
+ window = MainWindow(None, None)
+ qtbot.addWidget(window)
+ window.settings.setValue("outputWidth", 1920)
+ window.settings.setValue("outputHeight", 1080)
+ yield window
+
+
+def test_undo_classic_visualizer_sensitivity(window, qtbot):
+ """Undo Classic Visualizer component sensitivity setting
+ should undo multiple merged actions."""
+ window.core.insertComponent(
+ 0, window.core.moduleIndexFor("Classic Visualizer"), window
+ )
+ comp = window.core.selectedComponents[0]
+ comp.imagePath = getTestDataPath("test.jpg")
+ for i in range(1, 100):
+ comp.page.spinBox_scale.setValue(i)
+ assert comp.scale == 99
+ window.undoStack.undo()
+ assert comp.scale == 20
+
+
+def test_undo_image_scale(window, qtbot):
+ """Undo Image component scale setting should undo multiple merged actions."""
+ window.core.insertComponent(0, window.core.moduleIndexFor("Image"), window)
+ comp = window.core.selectedComponents[0]
+ comp.imagePath = getTestDataPath("test.jpg")
+ comp.page.spinBox_scale.setValue(100)
+ for i in range(10, 401):
+ comp.page.spinBox_scale.setValue(i)
+ assert comp.scale == 400
+ window.undoStack.undo()
+ assert comp.scale == 10
+ window.undoStack.undo()
+ assert comp.scale == 100
+
+
+def test_undo_image_resizeMode(window, qtbot):
+ window.core.insertComponent(0, window.core.moduleIndexFor("Image"), window)
+ comp = window.core.selectedComponents[0]
+ comp.page.comboBox_resizeMode.setCurrentIndex(1)
+ assert not comp.page.spinBox_scale.isEnabled()
+ window.undoStack.undo()
+ assert comp.page.spinBox_scale.isEnabled()
+
+
+def test_undo_title_text_merged(window, qtbot):
+ """Undoing title text change should undo all recent changes."""
+ window.core.insertComponent(0, window.core.moduleIndexFor("Title Text"), window)
+ comp = window.core.selectedComponents[0]
+ comp.page.lineEdit_title.setText("avp")
+ comp.page.lineEdit_title.setText("test")
+ window.undoStack.undo()
+ assert comp.title == "Text"
+
+
+def test_undo_title_text_not_merged(window, qtbot):
+ """Undoing title text change should undo up to previous different action"""
+ window.core.insertComponent(0, window.core.moduleIndexFor("Title Text"), window)
+ comp = window.core.selectedComponents[0]
+ comp.page.lineEdit_title.setText("avp")
+ comp.page.spinBox_xTextAlign.setValue(0)
+ comp.page.lineEdit_title.setText("test")
+ window.undoStack.undo()
+ assert comp.title == "avp"
diff --git a/tests/test_text_comp.py b/tests/test_text_comp.py
new file mode 100644
index 0000000..3bc0be6
--- /dev/null
+++ b/tests/test_text_comp.py
@@ -0,0 +1,32 @@
+from avp.command import Command
+from pytestqt import qtbot
+from pytest import fixture
+from . import audioData, MockSignal, imageDataSum
+
+
+@fixture
+def coreWithTextComp(qtbot):
+ """Fixture providing a Command object with Title Text component added"""
+ command = Command()
+ command.core.insertComponent(0, command.core.moduleIndexFor("Title Text"), command)
+ yield command.core
+
+
+def test_comp_text_renderFrame_resize(coreWithTextComp):
+ """Call renderFrame of Title Text component added to Command object."""
+ comp = coreWithTextComp.selectedComponents[0]
+ comp.parent.settings.setValue("outputWidth", 1920)
+ comp.parent.settings.setValue("outputHeight", 1080)
+ comp.parent.core.updateComponent(0)
+ image = comp.frameRender(0)
+ assert imageDataSum(image) == 2957069
+
+
+def test_comp_text_renderFrame(coreWithTextComp):
+ """Call renderFrame of Title Text component added to Command object."""
+ comp = coreWithTextComp.selectedComponents[0]
+ comp.parent.settings.setValue("outputWidth", 1280)
+ comp.parent.settings.setValue("outputHeight", 720)
+ comp.parent.core.updateComponent(0)
+ image = comp.frameRender(0)
+ assert imageDataSum(image) == 1412293 or 1379298
diff --git a/tests/test_toolkit_common.py b/tests/test_toolkit_common.py
new file mode 100644
index 0000000..d903842
--- /dev/null
+++ b/tests/test_toolkit_common.py
@@ -0,0 +1,13 @@
+from pytestqt import qtbot
+from avp.command import Command
+from avp.toolkit import blockSignals
+
+
+def test_blockSignals(qtbot):
+ command = Command()
+ command.core.insertComponent(0, 0, command)
+ comp = command.core.selectedComponents[0]
+ assert comp.page.spinBox_scale.signalsBlocked() == False
+ with blockSignals(comp.page.spinBox_scale):
+ assert comp.page.spinBox_scale.signalsBlocked() == True
+ assert comp.page.spinBox_scale.signalsBlocked() == False
diff --git a/tests/test_toolkit_ffmpeg.py b/tests/test_toolkit_ffmpeg.py
new file mode 100644
index 0000000..b015470
--- /dev/null
+++ b/tests/test_toolkit_ffmpeg.py
@@ -0,0 +1,64 @@
+import pytest
+from avp.command import Command
+from avp.toolkit.ffmpeg import createFfmpegCommand
+from . import audioData
+
+
+def test_readAudioFile_data(audioData):
+ assert len(audioData[0]) == 218453
+
+
+def test_readAudioFile_duration(audioData):
+ assert audioData[1] == 3.95
+
+
+@pytest.mark.parametrize("width, height", ((1920, 1080), (1280, 720)))
+def test_createFfmpegCommand(width, height):
+ command = Command()
+ command.settings.setValue("outputWidth", width)
+ command.settings.setValue("outputHeight", height)
+ ffmpegCmd = createFfmpegCommand("test.ogg", "/tmp", command.core.selectedComponents)
+ assert ffmpegCmd == [
+ "ffmpeg",
+ "-thread_queue_size",
+ "512",
+ "-y",
+ "-f",
+ "rawvideo",
+ "-vcodec",
+ "rawvideo",
+ "-s",
+ "%sx%s" % (width, height),
+ "-pix_fmt",
+ "rgba",
+ "-r",
+ "30",
+ "-t",
+ "0.100",
+ "-an",
+ "-i",
+ "-",
+ "-t",
+ "0.100",
+ "-i",
+ "test.ogg",
+ "-map",
+ "0:v",
+ "-map",
+ "1:a",
+ "-vcodec",
+ "libx264",
+ "-acodec",
+ "aac",
+ "-b:v",
+ "2500k",
+ "-b:a",
+ "192k",
+ "-pix_fmt",
+ "yuv420p",
+ "-preset",
+ "medium",
+ "-f",
+ "mp4",
+ "/tmp",
+ ]
diff --git a/tests/test_toolkit_frame.py b/tests/test_toolkit_frame.py
new file mode 100644
index 0000000..9486227
--- /dev/null
+++ b/tests/test_toolkit_frame.py
@@ -0,0 +1,14 @@
+import numpy
+from avp.toolkit.frame import BlankFrame, FloodFrame
+
+
+def test_blank_frame():
+ """BlankFrame creates a frame of all zeros"""
+ assert numpy.asarray(BlankFrame(1920, 1080), dtype="int32").sum() == 0
+
+
+def test_flood_frame():
+ """FloodFrame given (1, 1, 1, 1) creates a frame of sum 1920 * 1080 * 4"""
+ assert numpy.asarray(FloodFrame(1920, 1080, (1, 1, 1, 1)), dtype="int32").sum() == (
+ 1920 * 1080 * 4
+ )