diff --git a/poetry.lock b/poetry.lock
index de4b7bcfb332839793df1d801a4b38d0264ad00a..bda0ede59e0968a8505efe4f830526990656c863 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -126,18 +126,12 @@ python-versions = ">=3.7"
 license = ["ukkonen"]
 
 [[package]]
-name = "isort"
-version = "5.10.1"
-description = "A Python utility / library to sort Python imports."
+name = "iniconfig"
+version = "1.1.1"
+description = "iniconfig: brain-dead simple config-ini parsing"
 category = "dev"
 optional = false
-python-versions = ">=3.6.1,<4.0"
-
-[package.extras]
-pipfile_deprecated_finder = ["pipreqs", "requirementslib"]
-requirements_deprecated_finder = ["pipreqs", "pip-api"]
-colors = ["colorama (>=0.4.3,<0.5.0)"]
-plugins = ["setuptools"]
+python-versions = "*"
 
 [[package]]
 name = "mccabe"
@@ -147,14 +141,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[[package]]
-name = "more-itertools"
-version = "8.12.0"
-description = "More routines for operating on iterables, beyond itertools"
-category = "dev"
-optional = false
-python-versions = ">=3.5"
-
 [[package]]
 name = "mypy"
 version = "0.931"
@@ -221,14 +207,15 @@ test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock
 
 [[package]]
 name = "pluggy"
-version = "0.13.1"
+version = "1.0.0"
 description = "plugin and hook calling mechanisms for python"
 category = "dev"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=3.6"
 
 [package.extras]
 dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
 
 [[package]]
 name = "pre-commit"
@@ -283,25 +270,24 @@ diagrams = ["jinja2", "railroad-diagrams"]
 
 [[package]]
 name = "pytest"
-version = "5.4.3"
+version = "7.1.1"
 description = "pytest: simple powerful testing with Python"
 category = "dev"
 optional = false
-python-versions = ">=3.5"
+python-versions = ">=3.7"
 
 [package.dependencies]
 atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
-attrs = ">=17.4.0"
+attrs = ">=19.2.0"
 colorama = {version = "*", markers = "sys_platform == \"win32\""}
-more-itertools = ">=4.0.0"
+iniconfig = "*"
 packaging = "*"
-pluggy = ">=0.12,<1.0"
-py = ">=1.5.0"
-wcwidth = "*"
+pluggy = ">=0.12,<2.0"
+py = ">=1.8.2"
+tomli = ">=1.0.0"
 
 [package.extras]
-checkqa-mypy = ["mypy (==v0.761)"]
-testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
+testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
 
 [[package]]
 name = "pyyaml"
@@ -372,18 +358,10 @@ six = ">=1.9.0,<2"
 docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"]
 testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"]
 
-[[package]]
-name = "wcwidth"
-version = "0.2.5"
-description = "Measures the displayed width of unicode strings in a terminal"
-category = "dev"
-optional = false
-python-versions = "*"
-
 [metadata]
 lock-version = "1.1"
 python-versions = ">=3.9,<3.11"
-content-hash = "6f4fb43a3eb03bef2f49af983c6f3badb40dfae20eb298a2e675822bc2477752"
+content-hash = "ab1f88cbf02688daeb723c77086aedf337fd9c15eac50157c4b0481537be2098"
 
 [metadata.files]
 "aspy.refactor-imports" = [
@@ -430,18 +408,14 @@ identify = [
     {file = "identify-2.4.12-py2.py3-none-any.whl", hash = "sha256:5f06b14366bd1facb88b00540a1de05b69b310cbc2654db3c7e07fa3a4339323"},
     {file = "identify-2.4.12.tar.gz", hash = "sha256:3f3244a559290e7d3deb9e9adc7b33594c1bc85a9dd82e0f1be519bf12a1ec17"},
 ]
-isort = [
-    {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"},
-    {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"},
+iniconfig = [
+    {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
+    {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
 ]
 mccabe = [
     {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
     {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
 ]
-more-itertools = [
-    {file = "more-itertools-8.12.0.tar.gz", hash = "sha256:7dc6ad46f05f545f900dd59e8dfb4e84a4827b97b3cfecb175ea0c7d247f6064"},
-    {file = "more_itertools-8.12.0-py3-none-any.whl", hash = "sha256:43e6dd9942dffd72661a2c4ef383ad7da1e6a3e968a927ad7a6083ab410a688b"},
-]
 mypy = [
     {file = "mypy-0.931-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c5b42d0815e15518b1f0990cff7a705805961613e701db60387e6fb663fe78a"},
     {file = "mypy-0.931-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c89702cac5b302f0c5d33b172d2b55b5df2bede3344a2fbed99ff96bddb2cf00"},
@@ -485,8 +459,8 @@ platformdirs = [
     {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"},
 ]
 pluggy = [
-    {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
-    {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
+    {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
+    {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
 ]
 pre-commit = [
     {file = "pre_commit-2.17.0-py2.py3-none-any.whl", hash = "sha256:725fa7459782d7bec5ead072810e47351de01709be838c2ce1726b9591dad616"},
@@ -509,8 +483,8 @@ pyparsing = [
     {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"},
 ]
 pytest = [
-    {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"},
-    {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"},
+    {file = "pytest-7.1.1-py3-none-any.whl", hash = "sha256:92f723789a8fdd7180b6b06483874feca4c48a5c76968e03bb3e7f806a1869ea"},
+    {file = "pytest-7.1.1.tar.gz", hash = "sha256:841132caef6b1ad17a9afde46dc4f6cfa59a05f9555aae5151f73bdf2820ca63"},
 ]
 pyyaml = [
     {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
@@ -571,7 +545,3 @@ virtualenv = [
     {file = "virtualenv-20.13.4-py2.py3-none-any.whl", hash = "sha256:c3e01300fb8495bc00ed70741f5271fc95fed067eb7106297be73d30879af60c"},
     {file = "virtualenv-20.13.4.tar.gz", hash = "sha256:ce8901d3bbf3b90393498187f2d56797a8a452fb2d0d7efc6fd837554d6f679c"},
 ]
-wcwidth = [
-    {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
-    {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
-]
diff --git a/pyproject.toml b/pyproject.toml
index d0e7fb4196d2519ac7634e05be43a81e3e9eb032..5a9b7d15dbbd7130870edfd8016a3fe9df06df0c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -18,13 +18,12 @@ repository = "https://gitlab.control.lth.se/selectica/py_ur_ctl"
 python = ">=3.9,<3.11"
 
 [tool.poetry.dev-dependencies]
-pytest = "^5.2"
-isort = "^5.10.1"
 flake8 = "^4.0.1"
 mypy = "^0.931"
 black = "^21.12b0"
 pre-commit = "^2.17.0"
 reorder-python-imports = "^3.0.1"
+pytest = "^7.1.1"
 
 [tool.isort]
 profile = "black"
diff --git a/tests/test_urscript_commands.py b/tests/test_urscript_commands.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd56c54314cabf08f03e5b4b88a4697bd1212d65
--- /dev/null
+++ b/tests/test_urscript_commands.py
@@ -0,0 +1,60 @@
+import pytest
+
+from ur_py_ctl.urscript_commands import _add_whitespace
+from ur_py_ctl.urscript_commands import _get_conf
+from ur_py_ctl.urscript_commands import _get_func
+from ur_py_ctl.urscript_commands import _get_pose
+
+
+@pytest.fixture()
+def conf_list():
+    return [50, 25, 12.5, 100, 270, 360]
+
+
+@pytest.fixture
+def conf_str():
+    return "[50.00000, 25.00000, 12.50000, 100.00000, 270.00000, 360.00000]"
+
+
+@pytest.fixture()
+def pose_list():
+    return [22, 13, 25, 3.14, 0, 1.7]
+
+
+@pytest.fixture()
+def pose_str():
+    return "p[22.00000, 13.00000, 25.00000, 3.14000, 0.00000, 1.70000]"
+
+
+def test__add_whitespace():
+    def func(input_):
+        return input_[::-1]
+
+    wrapped_func = _add_whitespace(func)
+
+    input_ = "polyscope"
+
+    output = wrapped_func(input_)
+
+    assert output[0] == "\t"
+    assert output[-1] == "\n"
+    assert output.strip() == func(input_)
+
+
+def test_get_func():
+    func_name = "func"
+    urscript_args = "args"
+    urscript_kwargs = "kwargs"
+
+    assert (
+        _get_func(func_name, urscript_args, urscript_kwargs)
+        == f"{func_name}({urscript_args}, {urscript_kwargs})"
+    )
+
+
+def test__get_conf(conf_list, conf_str):
+    assert _get_conf(*conf_list) == conf_str
+
+
+def test__get_pose(pose_list, pose_str):
+    assert _get_pose(*pose_list) == pose_str
diff --git a/ur_py_ctl/urscript_commands.py b/ur_py_ctl/urscript_commands.py
index d14711900d58c3edcfc5d67b97da7b13a04cee22..e4b6bb9c0c8db79d46a7de6fe9c4dbebee1d33e9 100644
--- a/ur_py_ctl/urscript_commands.py
+++ b/ur_py_ctl/urscript_commands.py
@@ -26,7 +26,7 @@ def _get_pose(x: float, y: float, z: float, ax: float, ay: float, az: float) ->
     return f"p[{x:.5f}, {y:.5f}, {z:.5f}, {ax:.5f}, {ay:.5f}, {az:.5f}]"
 
 
-def _get_conf(j1, j2, j3, j4, j5, j6):
+def _get_conf(j1: float, j2: float, j3: float, j4: float, j5: float, j6: float):
     return f"[{j1:.5f}, {j2:.5f}, {j3:.5f}, {j4:.5f}, {j5:.5f}, {j6:.5f}]"
 
 
@@ -48,24 +48,47 @@ def _get_move_kwargs(**kwargs) -> str:
 
 
 @_add_whitespace
-def set_tcp(*args) -> str:
-    return _get_func("set_tcp", _get_pose(*args))
+def set_tcp(x: float, y: float, z: float, rx: float, ry: float, rz: float) -> str:
+    return _get_func("set_tcp", _get_pose(x, y, z, rx, ry, rz))
 
 
 @_add_whitespace
-def move_to_pose(*pose_args, mode=Motion.JOINT, **kwargs):
+def move_to_pose(
+    x: float,
+    y: float,
+    z: float,
+    rx: float,
+    ry: float,
+    rz: float,
+    mode=Motion.JOINT,
+    v: float = None,
+    a: float = None,
+    t: float = None,
+    r: float = None,
+) -> str:
     func_name = "movel" if mode == Motion.LINEAR else "movej"
 
-    pose = _get_pose(*pose_args)
-    move_kwargs = _get_move_kwargs(**kwargs)
+    pose = _get_pose(x, y, z, rx, ry, rz)
+    move_kwargs = _get_move_kwargs(v=v, a=a, t=t, r=r)
 
     return _get_func(func_name, pose, move_kwargs)
 
 
 @_add_whitespace
-def move_to_conf(*conf_args, **kwargs):
-    conf = _get_conf(*conf_args)
-    move_kwargs = _get_move_kwargs(**kwargs)
+def move_to_conf(
+    j1: float,
+    j2: float,
+    j3: float,
+    j4: float,
+    j5: float,
+    j6: float,
+    v: float = None,
+    a: float = None,
+    t: float = None,
+    r: float = None,
+) -> str:
+    conf = _get_conf(j1, j2, j3, j4, j5, j6)
+    move_kwargs = _get_move_kwargs(v=v, a=a, t=t, r=r)
 
     return _get_func("movej", conf, move_kwargs)
 
@@ -77,15 +100,24 @@ def textmsg(string: str) -> str:
 
 @_add_whitespace
 def set_DO(pin: int, state: bool) -> str:
-    return f"set_digital_out({pin:d}, {state})"
+    """Construct a function call that sets the state of a digital out."""
+    # bool(state) should convert numeric representation to boolean value and
+    # then into True or False as string.
+    return _get_func("set_digital_out", f"{pin:d}, {bool(state)}")
 
 
 @_add_whitespace
 def sleep(seconds: int) -> str:
-    return "sleep({})".format(seconds)
+    """Construct a function call that instructs the controller to sleep."""
+    return _get_func("sleep", str(seconds))
 
 
 @_add_whitespace
 def popup(string: str) -> str:
-    # Popup title not implemented, neither is error or warning flags
+    """Construct a function call that opens a popup on the teach pendant.
+
+    Notes
+    -----
+    Popup arguments title, error & warning is not implemented in URScript.
+    """
     return f'popup("{string}")'