Skip to content

Commit

Permalink
Tests!
Browse files Browse the repository at this point in the history
(and some infrastructure, and minor tweaks for testability and
that-never-worked-did-it)

Credit to @ghickman and @hashbangstudio whose tests I've squashed into
this!
  • Loading branch information
doismellburning committed Jun 7, 2015
1 parent 88646d9 commit 57c7e0c
Show file tree
Hide file tree
Showing 10 changed files with 349 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -1,2 +1,4 @@
*.egg-info
*.pyc
.coverage
.tox
11 changes: 9 additions & 2 deletions mcpi/connection.py
Expand Up @@ -31,10 +31,17 @@ def drain(self):
def send(self, f, *data):
"""Sends data. Note that a trailing newline '\n' is added here"""
s = "%s(%s)\n"%(f, flatten_parameters_to_string(data))
#print "f,data:",f,data
#print "s",s

self._send(s)

def _send(self, s):
"""
The actual socket interaction from self.send, extracted for easier mocking
and testing
"""
self.drain()
self.lastSent = s

self.socket.sendall(s)

def receive(self):
Expand Down
2 changes: 1 addition & 1 deletion mcpi/vec3.py
Expand Up @@ -16,7 +16,7 @@ def __iadd__(self, rhs):
return self

def length(self):
return self.lengthSqr ** .5
return self.lengthSqr() ** .5

def lengthSqr(self):
return self.x * self.x + self.y * self.y + self.z * self.z
Expand Down
30 changes: 30 additions & 0 deletions setup.py
@@ -0,0 +1,30 @@
import io
from setuptools import setup, find_packages
import sys

with io.open('README.rst', mode='r', encoding='utf8') as f:
readme = f.read()


setup(name='py3minepi',
version='0.0.1',
description='A better Minecraft Pi library.',
url='https://github.com/py3minepi/py3minepi',
packages=find_packages(exclude=['*.tests', '*.tests.*', 'tests.*', 'tests']),
zip_safe=True,
include_package_data=True,
keywords='minecraft raspberry pi mcpi py3minepi',
long_description=readme,
classifiers=[
'Development Status :: Development Status :: 3 - Alpha',
'Intended Audience :: Education',
'Intended Audience :: Developers',
'License :: OSI Approved :: Other/Proprietary License',
'Operating System :: POSIX',
'Operating System :: POSIX :: Linux',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
],
)
7 changes: 7 additions & 0 deletions tests/test_block.py
@@ -0,0 +1,7 @@
"""
Bare-bones but we don't even import block in any tests yet
"""

from mcpi import block

block.Block(block.AIR)
51 changes: 51 additions & 0 deletions tests/test_event.py
@@ -0,0 +1,51 @@
from mcpi.event import BlockEvent


class TestEvent():

def test_instantiation(self):
event_type = 0
pos = [14, 15, 16]
face = 2
entity = 1
event = BlockEvent(event_type, pos[0], pos[1], pos[2], face, entity)
assert event.type == event_type
assert event.pos.x == pos[0]
assert event.pos.y == pos[1]
assert event.pos.z == pos[2]
assert event.face == face
assert event.entityId == entity

def test_representation(self):
data = [0, 14, 15, 16, 1, 1]
event = BlockEvent(data[0], data[1], data[2],
data[3], data[4], data[5])
# block hit event has integer number converted in rep to text
expected = "BlockEvent(BlockEvent.HIT, 14, 15, 16, 1, 1)"
rep = repr(event)
assert rep == expected

def test_static_hit(self):
x = 89
y = -34
z = 30
event_type = 0
face = 3
entity = 1
# test the variable HIT
event = BlockEvent(BlockEvent.HIT, x, y, z, face, entity)
assert event.type == event_type
assert event.pos.x == x
assert event.pos.y == y
assert event.pos.z == z
assert event.face == face
assert event.entityId == entity

# test the static function
event_from_static = BlockEvent.Hit(x, y, z, face, entity)
assert event_from_static.type == event.type
assert event_from_static.pos.x == event.pos.x
assert event_from_static.pos.y == event.pos.y
assert event_from_static.pos.z == event.pos.z
assert event_from_static.face == event.face
assert event_from_static.entityId == event.entityId
12 changes: 12 additions & 0 deletions tests/test_minecraft.py
@@ -0,0 +1,12 @@
from mcpi.minecraft import intFloor


def test_int_floor_id():
intlist = [1, 2, 3]

assert intFloor(intlist) == intlist


def test_int_floor_floats():

assert type(intFloor([1.0])[0]) == int
94 changes: 94 additions & 0 deletions tests/test_usage.py
@@ -0,0 +1,94 @@
"""
API compatibility tests based on http://www.raspberrypi.org/documentation/usage/minecraft/
We do not want to break this API - we do not want to be responsible for sad children
(and adults) whose awesome Minecraft code no longer works.
Ergo this suite is a translation of that usage guide
Currently it doesn't actually test the __success__ of any of these commands, but it at
least verifies that the commands still exist, which is the most likely cause of breakage
"""

import pytest

from mcpi import minecraft
from mcpi import block
from mcpi.vec3 import Vec3
from time import sleep


@pytest.fixture(autouse=True)
def mc(monkeypatch):
monkeypatch.setattr("socket.socket.connect", lambda x, y: None)
monkeypatch.setattr("socket.socket.sendall", lambda x, y: None)

def dummy_send(self, command):
"""
Log, don't send, the command
"""

self.last_command_sent = command

monkeypatch.setattr("mcpi.connection.Connection._send", dummy_send)
monkeypatch.setattr("mcpi.minecraft.CmdPositioner.getPos", lambda x, y: Vec3(0.1, 0.1, 0.1))
return minecraft.Minecraft.create()


def test_hello_world(mc):
mc.postToChat("Hello world")

assert mc.conn.last_command_sent == "chat.post(Hello world)\n"


def test_get_pos(mc):
x, y, z = mc.player.getPos()


def test_teleport(mc):
x, y, z = mc.player.getPos()
mc.player.setPos(x, y + 100, z)


def test_set_block(mc):
x, y, z = mc.player.getPos()
mc.setBlock(x + 1, y, z, 1)

assert mc.conn.last_command_sent == "world.setBlock(%d,%d,%d,%d)\n" % (x + 1, y, z, 1)


def test_blocks_as_variables(mc):
x, y, z = mc.player.getPos()

dirt = block.DIRT.id
mc.setBlock(x, y, z, dirt)


def test_special_blocks(mc):
x, y, z = mc.player.getPos()

wool = 35
mc.setBlock(x, y, z, wool, 1)


def test_set_blocks(mc):
stone = 1
x, y, z = mc.player.getPos()
mc.setBlocks(x + 1, y + 1, z + 1, x + 11, y + 11, z + 11, stone)


def test_dropping_blocks_as_you_walk(mc):
"""
'The following code will drop a flower behind you wherever you walk'
We're not walking, and we don't want the infinite loop from the example, but this should do
Note that the actual example uses xrange which is not in Python 3, so lets test with range
"""

flower = 38

for i in range(10):
x, y, z = mc.player.getPos()
mc.setBlock(x, y, z, flower)
sleep(0.1)
134 changes: 134 additions & 0 deletions tests/test_vec3.py
@@ -0,0 +1,134 @@
from mcpi.vec3 import Vec3


class TestVec3():
""" Test the functions of the Vec3 class """

def test_instantiation(self):
expect_x = -1.0
expect_y = 4.0
expect_z = 6.0
v = Vec3(expect_x, expect_y, expect_z)
assert v.x == expect_x
assert v.y == expect_y
assert v.z == expect_z

vector3 = Vec3(1, -2, 3)
assert vector3.x == 1
assert vector3.y == -2
assert vector3.z == 3

assert vector3.x != -1
assert vector3.y != +2
assert vector3.z != -3

def test_representation(self):
# Test repr
v1 = Vec3(2, -3, 8)
expected_string = "Vec3({},{},{})".format(v1.x, v1.y, v1.z)
rep = repr(v1)
assert rep == expected_string
e = eval(repr(v1))
assert e == v1

def test_iteration(self):
coords = [1, 9, 6]
v = Vec3(coords[0], coords[1], coords[2])
for index, pos in enumerate(v):
assert pos == coords[index]

def test_equality(self):
v1 = Vec3(2, -3, 8)
v_same = Vec3(2, -3, 8)
v_diff = Vec3(22, 63, 88)
v_x_larger = Vec3(5, -3, 8)
v_x_smaller = Vec3(0, -3, 8)
v_y_larger = Vec3(2, 9, 8)
v_y_smaller = Vec3(2, -10, 8)
v_z_larger = Vec3(2, -3, 12)
v_z_smaller = Vec3(2, -3, 4)

assert v1 == v_same
assert not v1 == v_diff
assert v1 != v_diff

otherVectors = [v_x_larger, v_y_larger, v_z_larger,
v_x_smaller, v_y_smaller, v_z_smaller]

for other in otherVectors:
assert v1 != other

for other in otherVectors:
assert not v1 == other

def test_cloning(self):
v = Vec3(2, -3, 8)
v_clone = v.clone()
assert v == v_clone
v.x += 1
assert v != v_clone

def test_negation(self):
v1 = Vec3(2, -3, 8)
v_inverse = -v1
assert v1.x == -v_inverse.x
assert v1.y == -v_inverse.y
assert v1.z == -v_inverse.z

def test_addition(self):
a = Vec3(10, -3, 4)
b = Vec3(-7, 1, 2)
c = a + b
totV = Vec3(3, -2, 6)
assert c == totV
assert c - a == b
assert c - b == a

def test_subtraction(self):
a = Vec3(10, -3, 4)
b = Vec3(5, 3, 5)
assert (a - a) == Vec3(0, 0, 0)
assert (a + (-a)) == Vec3(0, 0, 0)
assert (a - b) == Vec3(5, -6, -1)

def test_multiplication(self):
a = Vec3(2, -3, 8)
assert (a + a) == (a * 2)
k = 4
a *= k
assert a == Vec3(2 * k, -3 * k, 8 * k)

def test_length(self):
v = Vec3(2.0, -3.0, 8.0)
length = v.length()
expect_length = (((2 * 2) + (-3 * -3) + (8 * 8)) ** 0.5)
assert length == expect_length

def test_length_sqr(self):
v = Vec3(2, -3, 8)
ls = v.lengthSqr()
assert ls == ((2 * 2) + (-3 * -3) + (8 * 8))

def test_iround(self):
v = Vec3(2.3, -3.7, 8.8)
v.iround()
expect_vec = Vec3(2, -3, 9)
assert v == expect_vec

def test_ifloor(self):
v = Vec3(2.3, -3.7, 8.8)
v.ifloor()
expect_vec = Vec3(2, -3, 8)
assert v == expect_vec

def test_rotate_left(self):
v = Vec3(2, -3, 8)
v.rotateLeft()
expect_vec = Vec3(8, -3, -2)
assert v == expect_vec

def test_rotate_right(self):
v = Vec3(2, -3, 8)
v.rotateRight()
expect_vec = Vec3(-8, -3, 2)
assert v == expect_vec
9 changes: 9 additions & 0 deletions tox.ini
@@ -0,0 +1,9 @@
[tox]
envlist =
py27

[testenv]
deps =
pytest
commands =
py.test

0 comments on commit 57c7e0c

Please sign in to comment.