Skip to content

Commit 2b24c4f

Browse files
Prepared code for the testing section of the chapter.
1 parent 0f8aa1f commit 2b24c4f

7 files changed

Lines changed: 455 additions & 0 deletions

File tree

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// This sample test demonstrates the basic usage of the
2+
// testing package.
3+
package listing01
4+
5+
import (
6+
"encoding/xml"
7+
"net/http"
8+
"testing"
9+
)
10+
11+
const succeed = "\u2713"
12+
const failed = "\u2717"
13+
14+
// Item defines the fields associated with the item tag in
15+
// the buoy RSS document.
16+
type Item struct {
17+
XMLName xml.Name `xml:"item"`
18+
PubDate string `xml:"pubDate"`
19+
Title string `xml:"title"`
20+
Description string `xml:"description"`
21+
Link string `xml:"link"`
22+
GUID string `xml:"guid"`
23+
GeoRssPoint string `xml:"georss:point"`
24+
}
25+
26+
// Image defines the fields associated with the image tag in
27+
// the buoy RSS document.
28+
type Image struct {
29+
XMLName xml.Name `xml:"image"`
30+
URL string `xml:"url"`
31+
Title string `xml:"title"`
32+
Link string `xml:"link"`
33+
}
34+
35+
// Channel defines the fields associated with the channel tag in
36+
// the buoy RSS document.
37+
type Channel struct {
38+
XMLName xml.Name `xml:"channel"`
39+
Title string `xml:"title"`
40+
Description string `xml:"description"`
41+
Link string `xml:"link"`
42+
PubDate string `xml:"pubDate"`
43+
LastBuildDate string `xml:"lastBuildDate"`
44+
TTL string `xml:"ttl"`
45+
Language string `xml:"language"`
46+
ManagingEditor string `xml:"managingEditor"`
47+
WebMaster string `xml:"webMaster"`
48+
Image Image `xml:"image"`
49+
Items []Item `xml:"item"`
50+
}
51+
52+
// Document defines the fields associated with the buoy RSS document.
53+
type Document struct {
54+
XMLName xml.Name `xml:"rss"`
55+
Channel Channel `xml:"channel"`
56+
URI string
57+
}
58+
59+
// TestDownload tests if download web content is working.
60+
func TestDownload(t *testing.T) {
61+
URL := "http://www.goinggo.net/feeds/posts/default?alt=rss"
62+
63+
t.Log("Given the need to test downloading content.")
64+
{
65+
resp, err := http.Get(URL)
66+
if err == nil {
67+
t.Log("\tShould be able to make the Get call.",
68+
succeed)
69+
} else {
70+
t.Fatal("\tShould be able to make the Get call.",
71+
failed, err)
72+
}
73+
74+
defer resp.Body.Close()
75+
76+
if resp.StatusCode == 200 {
77+
t.Log("\tShould receive a \"200\" status code.",
78+
succeed)
79+
} else {
80+
t.Error("\tShould receive a \"200\" status code.",
81+
failed, resp.StatusCode)
82+
}
83+
84+
var d Document
85+
if err := xml.NewDecoder(resp.Body).Decode(&d); err == nil {
86+
t.Log("\tShould be able to unmarshal the response.",
87+
succeed)
88+
} else {
89+
t.Fatal("\tShould be able to unmarshal the response.",
90+
failed, err)
91+
}
92+
93+
if len(d.Channel.Items) == 1 {
94+
t.Log("\tShould have \"1\" item in the feed.",
95+
succeed)
96+
} else {
97+
t.Fatal("\tShould have \"1\" item in the feed.",
98+
failed, len(d.Channel.Items))
99+
}
100+
}
101+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// This sample test demonstrates how to mock client HTTP calls.
2+
package listing02
3+
4+
import (
5+
"encoding/xml"
6+
"fmt"
7+
"net/http"
8+
"net/http/httptest"
9+
"testing"
10+
)
11+
12+
const succeed = "\u2713"
13+
const failed = "\u2717"
14+
15+
var feed = `<?xml version="1.0" encoding="UTF-8"?>
16+
<rss xmlns:atom="http://www.w3.org/2005/Atom"
17+
xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
18+
xmlns:blogger="http://schemas.google.com/blogger/2008"
19+
xmlns:georss="http://www.georss.org/georss"
20+
xmlns:gd="http://schemas.google.com/g/2005"
21+
xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0">
22+
<channel>
23+
<atom:id>tag:blogger.com,1999:blog-6298089572270107210</atom:id>
24+
<lastBuildDate>Mon, 27 Apr 2015 12:42:23 +0000</lastBuildDate>
25+
<title>Going Go Programming</title>
26+
<description>Golang For The Common Man : https://github.com/goinggo</description>
27+
<link>http://www.goinggo.net/</link>
28+
<managingEditor>noreply@blogger.com (William Kennedy)</managingEditor>
29+
<generator>Blogger</generator>
30+
<openSearch:totalResults>67</openSearch:totalResults>
31+
<openSearch:startIndex>1</openSearch:startIndex>
32+
<openSearch:itemsPerPage>25</openSearch:itemsPerPage>
33+
<item>
34+
<guid isPermaLink="false">tag:blogger.com,1999:blog-6298089572270107210.post-3707264680032475251</guid>
35+
<pubDate>Sun, 15 Mar 2015 15:04:00 +0000</pubDate>
36+
<atom:updated>2015-03-15T11:21:09.934-04:00</atom:updated>
37+
<title>Object Oriented Programming Mechanics</title>
38+
<description>&lt;div class="p1"&gt;Go is an object oriented programming language. It may not have inheritance, but in this 20 minute video from the Bangalore meetup, I will show you how object oriented programming practices and techniques can be applied to your Go programs. From an object oriented standpoint, Go does provides the ability to add behavior to your types via methods, allows you to implement polymorphic behavior via interfaces and gives you a way to extend the state and behavior of any existing type via type embedding. Go also provides a form of encapsulation that allows your types, including their fields and methods, to be visible or invisible. Everything you need to write object oriented programs is available in Go.&lt;/div&gt;&lt;br /&gt;&lt;iframe allowfullscreen="" frameborder="0" height="510" src="https://www.youtube.com/embed/gRpUfjTwSOo" width="100%"&gt;&lt;/iframe&gt; &lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;b&gt;Example 1 - Methods: &lt;/b&gt;&lt;br /&gt;&lt;a href="http://play.golang.org/p/hfRkC6nKag" target="_blank"&gt;http://play.golang.org/p/hfRkC6nKag&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Example 2 - Interfaces:&lt;/b&gt;&lt;br /&gt;&lt;a href="http://play.golang.org/p/F1UyKlTh3k" target="_blank"&gt;http://play.golang.org/p/F1UyKlTh3k&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Example 3 - Extending Types:&lt;/b&gt;&lt;br /&gt;&lt;a href="http://play.golang.org/p/JJ811lBwoz" target="_blank"&gt;http://play.golang.org/p/JJ811lBwoz&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Example 4 - Overriding Inner Types:&lt;/b&gt;&lt;br /&gt;&lt;a href="http://play.golang.org/p/-xQFBv9_82" target="_blank"&gt;http://play.golang.org/p/-xQFBv9_82&lt;/a&gt;</description>
39+
<link>http://www.goinggo.net/2015/03/object-oriented-programming-mechanics.html</link>
40+
<author>noreply@blogger.com (William Kennedy)</author>
41+
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/gRpUfjTwSOo/default.jpg" height="72" width="72"/>
42+
<thr:total>0</thr:total>
43+
</item>
44+
</channel>
45+
</rss>`
46+
47+
// Item defines the fields associated with the item tag in
48+
// the buoy RSS document.
49+
type Item struct {
50+
XMLName xml.Name `xml:"item"`
51+
PubDate string `xml:"pubDate"`
52+
Title string `xml:"title"`
53+
Description string `xml:"description"`
54+
Link string `xml:"link"`
55+
GUID string `xml:"guid"`
56+
GeoRssPoint string `xml:"georss:point"`
57+
}
58+
59+
// Image defines the fields associated with the image tag in
60+
// the buoy RSS document.
61+
type Image struct {
62+
XMLName xml.Name `xml:"image"`
63+
URL string `xml:"url"`
64+
Title string `xml:"title"`
65+
Link string `xml:"link"`
66+
}
67+
68+
// Channel defines the fields associated with the channel tag in
69+
// the buoy RSS document.
70+
type Channel struct {
71+
XMLName xml.Name `xml:"channel"`
72+
Title string `xml:"title"`
73+
Description string `xml:"description"`
74+
Link string `xml:"link"`
75+
PubDate string `xml:"pubDate"`
76+
LastBuildDate string `xml:"lastBuildDate"`
77+
TTL string `xml:"ttl"`
78+
Language string `xml:"language"`
79+
ManagingEditor string `xml:"managingEditor"`
80+
WebMaster string `xml:"webMaster"`
81+
Image Image `xml:"image"`
82+
Items []Item `xml:"item"`
83+
}
84+
85+
// Document defines the fields associated with the buoy RSS document.
86+
type Document struct {
87+
XMLName xml.Name `xml:"rss"`
88+
Channel Channel `xml:"channel"`
89+
URI string
90+
}
91+
92+
// mockServer returns a pointer to a server to handle the mock get call.
93+
func mockServer() *httptest.Server {
94+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
95+
w.WriteHeader(200)
96+
w.Header().Set("Content-Type", "application/xml")
97+
fmt.Fprintln(w, feed)
98+
}))
99+
return server
100+
}
101+
102+
// TestDownload tests if download web content is working.
103+
func TestDownload(t *testing.T) {
104+
server := mockServer()
105+
defer server.Close()
106+
107+
t.Log("Given the need to test downloading content.")
108+
{
109+
resp, err := http.Get(server.URL)
110+
if err == nil {
111+
t.Log("\tShould be able to make the Get call.",
112+
succeed)
113+
} else {
114+
t.Fatal("\tShould be able to make the Get call.",
115+
failed, err)
116+
}
117+
118+
defer resp.Body.Close()
119+
120+
if resp.StatusCode == 200 {
121+
t.Log("\tShould receive a \"200\" status code.",
122+
succeed)
123+
} else {
124+
t.Error("\tShould receive a \"200\" status code.",
125+
failed, resp.StatusCode)
126+
}
127+
128+
var d Document
129+
if err := xml.NewDecoder(resp.Body).Decode(&d); err == nil {
130+
t.Log("\tShould be able to unmarshal the response.",
131+
succeed)
132+
} else {
133+
t.Fatal("\tShould be able to unmarshal the response.",
134+
failed, err)
135+
}
136+
137+
if len(d.Channel.Items) == 1 {
138+
t.Log("\tShould have \"1\" item in the feed.",
139+
succeed)
140+
} else {
141+
t.Fatal("\tShould have \"1\" item in the feed.",
142+
failed, len(d.Channel.Items))
143+
}
144+
}
145+
}

chapter9/listing03/example03.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// This sample code implement a web service.
2+
package main
3+
4+
import (
5+
"encoding/json"
6+
"log"
7+
"net/http"
8+
)
9+
10+
// main is the entry point for the application.
11+
func main() {
12+
Routes()
13+
14+
log.Println("listener : Started : Listening on: http://localhost:4000")
15+
http.ListenAndServe(":4000", nil)
16+
}
17+
18+
// Routes sets the routes for the web service.
19+
func Routes() {
20+
http.HandleFunc("/sendjson", SendJSON)
21+
}
22+
23+
// SendJSON returns a simple JSON document.
24+
func SendJSON(rw http.ResponseWriter, r *http.Request) {
25+
u := struct {
26+
Name string
27+
Email string
28+
}{
29+
Name: "Bill",
30+
Email: "bill@ardanstudios.com",
31+
}
32+
33+
rw.Header().Set("Content-Type", "application/json")
34+
rw.WriteHeader(200)
35+
36+
if err := json.NewEncoder(rw).Encode(u); err != nil {
37+
log.Panic(err)
38+
}
39+
40+
LogResponse(&u)
41+
}
42+
43+
// LogResponse is used to write the response to the log.
44+
func LogResponse(v interface{}) {
45+
d, err := json.MarshalIndent(v, "", " ")
46+
if err != nil {
47+
log.Println("Unable to Marshal Response", err)
48+
return
49+
}
50+
51+
log.Println(string(d))
52+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Sample example test for the LogResponse function.
2+
package main_test
3+
4+
import (
5+
"log"
6+
"os"
7+
8+
ex3 "github.com/ArdanStudios/gotraining/09-testing/01-testing/example3"
9+
)
10+
11+
// ExampleLogResponse provides a basic example test example.
12+
func ExampleLogResponse() {
13+
log.SetFlags(0)
14+
log.SetOutput(os.Stdout)
15+
16+
u := struct {
17+
Name string
18+
Email string
19+
}{
20+
Name: "Bill",
21+
Email: "bill@ardanstudios.com",
22+
}
23+
24+
ex3.LogResponse(&u)
25+
// Output:
26+
// {
27+
// "Name": "Bill",
28+
// "Email": "bill@ardanstudios.com"
29+
// }
30+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Sample unit test for testing an internal endpoint.
2+
package main_test
3+
4+
import (
5+
"encoding/json"
6+
"net/http"
7+
"net/http/httptest"
8+
"testing"
9+
10+
ex3 "github.com/ArdanStudios/gotraining/09-testing/01-testing/example3"
11+
)
12+
13+
const succeed = "\u2713"
14+
const failed = "\u2717"
15+
16+
func init() {
17+
ex3.Routes()
18+
}
19+
20+
// TestDownload tests if download web content is working.
21+
func TestSendJSON(t *testing.T) {
22+
t.Log("Given the need to test the SendJSON endpoint.")
23+
{
24+
r, _ := http.NewRequest("GET", "/sendjson", nil)
25+
w := httptest.NewRecorder()
26+
http.DefaultServeMux.ServeHTTP(w, r)
27+
28+
if w.Code != 200 {
29+
t.Fatalf("\tShould received a status code of 200 for the response. Received[%d] %s", w.Code, failed)
30+
}
31+
t.Log("\tShould received a status code of 200 for the response.", succeed)
32+
33+
u := struct {
34+
Name string
35+
Email string
36+
}{}
37+
if err := json.NewDecoder(w.Body).Decode(&u); err != nil {
38+
t.Fatal("\tShould be able to unmarshal the response.", failed)
39+
}
40+
t.Log("\tShould be able to unmarshal the response.", succeed)
41+
42+
if u.Name == "Bill" {
43+
t.Log("\tShould have \"Bill\" for Name in the response.", succeed)
44+
} else {
45+
t.Error("\tShould have \"Bill\" for Name in the response.", failed, u.Name)
46+
}
47+
48+
if u.Email == "bill@ardanstudios.com" {
49+
t.Log("\tShould have \"bill@ardanstudios.com\" for Email in the response.", succeed)
50+
} else {
51+
t.Error("\tShould have \"bill@ardanstudios.com\" for Email in the response.", failed, u.Email)
52+
}
53+
}
54+
}

0 commit comments

Comments
 (0)