diff --git a/__pycache__/camera.cpython-33.pyc b/__pycache__/camera.cpython-33.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7ac9cd14ce80218af0287c5e0f604d59b9c1e5cf
Binary files /dev/null and b/__pycache__/camera.cpython-33.pyc differ
diff --git a/__pycache__/intersection.cpython-33.pyc b/__pycache__/intersection.cpython-33.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fae1ae74b367b9008f501976711328e4472c8010
Binary files /dev/null and b/__pycache__/intersection.cpython-33.pyc differ
diff --git a/__pycache__/light.cpython-33.pyc b/__pycache__/light.cpython-33.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..25de9666d344f0b6096dd800e61ad58c1f75cdfd
Binary files /dev/null and b/__pycache__/light.cpython-33.pyc differ
diff --git a/__pycache__/operation_vector.cpython-33.pyc b/__pycache__/operation_vector.cpython-33.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..200dee8539d5beca61dbe0c0a5cc3b84ef2dcba1
Binary files /dev/null and b/__pycache__/operation_vector.cpython-33.pyc differ
diff --git a/__pycache__/raytracer.cpython-33.pyc b/__pycache__/raytracer.cpython-33.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d438c668c55e9e716dd620b8256fd685dab4b5db
Binary files /dev/null and b/__pycache__/raytracer.cpython-33.pyc differ
diff --git a/__pycache__/scene.cpython-33.pyc b/__pycache__/scene.cpython-33.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ac3f713769654225108a1111d89b0afaa5f39b8a
Binary files /dev/null and b/__pycache__/scene.cpython-33.pyc differ
diff --git a/camera.py b/camera.py
index a4e5e2347fbc09707b6870d2133024208fc041d9..083f32bdf7603e87e5d8f6ec2fda3564ed537ed4 100644
--- a/camera.py
+++ b/camera.py
@@ -1,4 +1,5 @@
 from operation_vector import Vector
+from raytracer import Ray
 
 class Camera:
     def __init__(self, image_nrows, image_ncols, distance_focale):
@@ -11,6 +12,6 @@ class Camera:
         x = (n-row)/n
         n = self.image_ncols//2
         y = (n-col)/n
-        return Vector((x, y, self.focal_length))
+        return Ray(Vector([0,0,0]), Vector((x, y, self.focal_length)))
 
     
diff --git a/light.py b/light.py
index c324f9d66aac43f5dec06a588ad9b6e0b3f38294..674fb4ea1105b6b63f1b27715bc37f765bd15f15 100644
--- a/light.py
+++ b/light.py
@@ -13,7 +13,13 @@ def phong_illuminate(light, position, normal, object, viewer):
     R = 2*(L*N)*N - L
     V = (viewer - position).normalized()
 
-    i = ((kd*(L*N) + ks*(R*V)**alpha))*(N*L > 0)
+    if (N*L) <= 0:
+        return 0*position
+    i = ((kd*(L*N) + ks*(R*V)**alpha))
+    if i < 0:
+        i = 0
+    elif i > 1:
+        i = 1
     
     return i*(light.color ** object.material.color)
     
diff --git a/one_sphere.png b/one_sphere.png
deleted file mode 100644
index 090a8d4f232416bfe3d6ea894b2eb203cac83bfb..0000000000000000000000000000000000000000
Binary files a/one_sphere.png and /dev/null differ
diff --git a/operation_vector.py b/operation_vector.py
index 0c9825c83c19c4005d54aff44dd6ae39547b6679..fe5ffd241221cd40c19373327dc9434580349cdd 100644
--- a/operation_vector.py
+++ b/operation_vector.py
@@ -3,12 +3,12 @@ from random import random
 class Vector:
     def __init__(self, coord):
         x, y, z = coord
-        self.x = x
-        self.y = y
-        self.z = z
+        self.x = float(x)
+        self.y = float(y)
+        self.z = float(z)
 
     def coord(self):
-        return (self.x, self.y, self.z)
+        return (float(self.x), float(self.y), float(self.z))
     
     def __add__(first, second):
         if type(second) == Vector:
@@ -19,7 +19,7 @@ class Vector:
     
     def __rmul__(vector, item):
         d, e, f = vector.coord()
-        return Vector((item*d, item*e, item*f))
+        return Vector((float(item*d), float(item*e), float(item*f)))
 
     def __radd__(vector, item):
         return vector + item
diff --git a/raytracer.py b/raytracer.py
index 4b746b31408141b2d1830ff7ddbcb2636311af38..fe34768add2db921f28bc0fd4393e2577df39d74 100644
--- a/raytracer.py
+++ b/raytracer.py
@@ -25,7 +25,7 @@ def trace_ray(ray, scene, camera):
         color += phong_illuminate(light, class_intersect.position, class_intersect.normal, class_intersect.object, Vector([0,0,0]))
     color_object = class_intersect.object.material.color
     c_x, c_y, c_z = color.coord()
-    return Vector([min(c_x,1), min(c_y,1), min(c_z,1)])
+    return Vector([max(min(c_x, 1), 0), max(0, min(c_y, 1)), max(0, min(c_z,1))])
 
 def raytracer_render(camera, scene):
     n_lignes = camera.image_nrows
@@ -33,8 +33,7 @@ def raytracer_render(camera, scene):
     affiche = zeros((n_lignes, n_colonnes,3))
     for i in range(n_lignes):
         for j in range(n_colonnes):
-            ray_direction = camera.ray_at(i, j)
-            ray = Ray(Vector((0,0,0)), ray_direction)
+            ray = camera.ray_at(i, j)
             color = trace_ray(ray, scene, camera)
             affiche[i,j,:] = color.coord()
     return affiche
diff --git a/scene.py b/scene.py
index ff44e7be4a0772fe083cf3b3c28253869ae5b527..c18a96bce3cfcdc353f36e09f7b6754cf9666f04 100644
--- a/scene.py
+++ b/scene.py
@@ -7,12 +7,13 @@ class Sphere:
         self.material = material
 
 class Material:
-    def __init__(self, color, ambiant, diffuse, specular, shininess):
+    def __init__(self, color, ambiant, diffuse, specular, shininess, reflection):
         self.color = color
         self.ambiant = ambiant
         self.diffuse = diffuse
         self.specular = specular
         self.shininess = shininess
+        self.reflection = reflection
 
 class Scene:
     def __init__(self):
diff --git a/script_one_sphere.py b/script_one_sphere.py
index ff511e40fb2a0223c721501a9bbdcce397667b54..eeec468916dc9534f061f79d1aa18c7423655a0e 100644
--- a/script_one_sphere.py
+++ b/script_one_sphere.py
@@ -3,13 +3,22 @@ from light import Spotlight
 from camera import Camera
 from raytracer import raytracer_render
 from matplotlib.image import imsave
+from math import cos, sin, pi
 
 camera = Camera(200,200,2)
-materiau_sphere = Material(Vector((0,0,1)), .1, .3, .8, 20)
+materiau_sphere = Material(Vector((0,0,1)), .5, .3, .7, 20, 1)
 sphere = Sphere(Vector([0,0,3]), 1, materiau_sphere)
-lumiere = Spotlight(Vector((1, 1, 0)), Vector((1,1,1)))
-scene = Scene()
-scene.add_object(sphere)
-scene.add_light(lumiere)
-affiche = raytracer_render(camera, scene)
-imsave('one_sphere.png',affiche)
+for theta in range(36):
+    a = 3*cos(theta*pi/18)
+    b = 3*sin(theta*pi/18)
+    lumiere = Spotlight(Vector((0, a, 3+b)), Vector((1,1,1)))
+    lumiere_2 = Spotlight(Vector((0, -a, 3-b)), Vector((1,1,1)))
+    scene = Scene()
+    scene.add_object(sphere)
+    scene.add_light(lumiere)
+    scene.add_light(lumiere_2)
+    affiche = raytracer_render(camera, scene)
+    imsave('one_sphere_' + str(theta) + '.png',affiche)
+    print(theta)
+    
+    
diff --git a/tests/01_camera_ok.py b/tests/01_camera_ok.py
new file mode 100644
index 0000000000000000000000000000000000000000..362b2281e2525e0b0606730ce50303d34dd42874
--- /dev/null
+++ b/tests/01_camera_ok.py
@@ -0,0 +1,14 @@
+# Show to python where to find the Camera module
+import sys
+sys.path.append('..')
+
+# Import the Camera module
+from camera import *
+
+# Instantiate a Camera object
+c = Camera(100, 200, 3)
+
+# Test its members
+assert(c.image_nrows == 100)
+assert(c.image_ncols == 200)
+assert(c.focal_length == 3)
diff --git a/tests/02_rayon_ok.py b/tests/02_rayon_ok.py
new file mode 100644
index 0000000000000000000000000000000000000000..1ce0c2f0970b1d1b089debc914b25d951318e8fa
--- /dev/null
+++ b/tests/02_rayon_ok.py
@@ -0,0 +1,31 @@
+# Show to python where to find the Camera module
+import sys
+sys.path.append('..')
+
+import numpy as np
+from camera import *
+from operation_vector import Vector
+
+c = Camera(100, 200, 3)
+
+r_center = c.ray_at(c.image_nrows / 2, c.image_ncols / 2);
+
+assert (abs(r_center.direction*Vector([0,0,1]) - r_center.direction.norm()) < 0.01, "c.ray_at(c.image_nrows / 2, c.image_ncols / 2) should have the direction [0,0,1].")
+
+r_zero = c.ray_at(0,0);
+
+r_zero_ref_dir = Vector([1,1,c.focal_length])
+r_zero_ref_dir = r_zero_ref_dir / r_zero_ref_dir.norm()
+
+assert abs(r_zero.direction* (r_zero_ref_dir) -
+        r_zero.direction.norm()) < 0.01, "c.ray_at(0,0) should have the direction [1,1,camera.focal_length].";
+
+
+r_one = c.ray_at(c.image_nrows, c.image_ncols);
+r_one_ref_dir = Vector([-1,-1,c.focal_length])
+r_one_ref_dir = r_one_ref_dir / r_one_ref_dir.norm()
+
+assert abs(r_one.direction*(r_one_ref_dir) -
+           r_one.direction.norm() < 0.01), "c.ray_at(c.nrows,c.ncols) should have the direction [-1,-1,c.focal_length.";
+
+
diff --git a/tests/03_sphere_intersection_ok.py b/tests/03_sphere_intersection_ok.py
new file mode 100644
index 0000000000000000000000000000000000000000..d7893c8e4c6da6384174ef4611ba33236fa7c6e4
--- /dev/null
+++ b/tests/03_sphere_intersection_ok.py
@@ -0,0 +1,33 @@
+# Show to python where to find the modules
+import sys
+sys.path.append('..')
+from operation_vector import Vector
+
+from scene import *
+from camera import *
+from intersection import *
+
+def is_parallel(v1, v2):
+    return ((v1*v2) / (v1.norm() * v2.norm()) - 1.) < 0.01
+
+s = Sphere(Vector([0,0,3]), 1, Material(Vector([0,0,1.]), 1, 1, 1, 1, 1))
+
+r = Ray(Vector([0,0,0]), Vector([0,0,1]))
+i = intersect(s, r)
+assert (i.position == Vector([0,0,2.])), "Error with a ray starting outside the sphere."
+assert is_parallel(i.normal, Vector([0,0,-1.])), "Error with the normal of a ray starting outside the sphere."
+
+r = Ray(Vector([0,0,10]), Vector([0,0,-1]))
+i = intersect(s, r)
+assert (i.position == Vector([0,0,4.])), "Error with a ray starting outside the sphere."
+assert is_parallel(i.normal, Vector([0,0,1.])), "Error with the normal of a ray starting outside the sphere."
+
+r = Ray(Vector([0,0,3]), Vector([0,0,-1]))
+i = intersect(s, r)
+assert (i.position == Vector([0,0,2.])), "Error with a ray starting inside the sphere."
+assert is_parallel(i.normal, Vector([0,0,1.])), "Error with the normal of a ray starting inside the sphere."
+
+r = Ray(Vector([0,0,5]), Vector([0,0,1]))
+i = intersect(s, r)
+assert i is None, "Error with a ray not intersecting the sphere: intersect should return None."
+
diff --git a/tests/04_material_ok.py b/tests/04_material_ok.py
new file mode 100644
index 0000000000000000000000000000000000000000..1f12e23d669524d4d76cae1dd4a4bd30634e81eb
--- /dev/null
+++ b/tests/04_material_ok.py
@@ -0,0 +1,14 @@
+import sys
+sys.path.append('..')
+from operation_vector import Vector
+
+from scene import *
+
+m = Material(Vector([0,0,1]), 0.1, 0.2, 0.3, 0.4, 0.5);
+
+assert((m.color == Vector([0,0,1])))
+assert(m.ambiant == 0.1)
+assert(m.diffuse == 0.2)
+assert(m.specular == 0.3)
+assert(m.shininess == 0.4)
+assert(m.reflection == 0.5)
diff --git a/tests/05_phong_ok.py b/tests/05_phong_ok.py
new file mode 100644
index 0000000000000000000000000000000000000000..9d7dedf6ab5d4dfd0c09d46e7bef9e6d35792abb
--- /dev/null
+++ b/tests/05_phong_ok.py
@@ -0,0 +1,32 @@
+# Show to python where to find the Camera module
+import sys
+sys.path.append('..')
+from operation_vector import Vector
+
+# Import the Camera module
+from scene import *
+from light import *
+
+s = Sphere(Vector([0,0,3]), 1, Material(Vector([0.1,0.2,0.3]), 0.1, 0.2, 0.3, 0.4, 0.5));
+n = Vector([0,0,-1])
+l = Spotlight(Vector([0,0,0]), Vector([0,0,1]));
+p = Vector([0,0,2])
+v = Vector([0,0,0])
+
+assert((phong_illuminate(l, p, n, s, v) == Vector([0,0,0.15])))
+
+s = Sphere(Vector([0,0,3]), 1, Material(Vector([0.1,0.2,0.3]), 0.1, 0.2, 0.3, 0.4, 0.5));
+n = Vector([0,0,-1])
+l = Spotlight(Vector([1,1,0]), Vector([0,0,1]));
+p = Vector([0,0,2])
+v = Vector([0,0,0])
+assert((phong_illuminate(l, p, n, s, v) - Vector([0, 0, 0.13])).norm() < 0.01)
+
+
+s = Sphere(Vector([0,0,3]), 1, Material(Vector([0.1,0.2,0.3]), 0.1, 0.2, 0.3, 0.4, 0.5));
+n = Vector([0,0,-1])
+l = Spotlight(Vector([0,0,10]), Vector([0,0,1]));
+p = Vector([0,0,2])
+v = Vector([0,0,0])
+assert((phong_illuminate(l, p, n, s, v) == Vector([0,0,0])))
+