The primary purpose of collaborative construction is to improve software quality. As
noted in Chapter 20, “The Software-Quality Landscape,” software testing has limited
effectiveness when used alone—the average defect-detection rate is only about 30 percent for unit testing, 35 percent for integration testing, and 35 percent for low-volume
beta testing. In contrast, the average effectivenesses of design and code inspections are
55 and 60 percent (Jones 1996). The secondary benefit of collaborative construction
is that it decreases development time, which in turn lowers development costs.
by《Code Complete》
Developer tests tend to be “clean tests” Developers tend to test for whether the code
works (clean tests) rather than test for all the ways the code breaks (dirty tests).
Immature testing organizations tend to have about five clean tests for every dirty test.
Mature testing organizations tend to have five dirty tests for every clean test. This ratio
is not reversed by reducing the clean tests; it’s done by creating 25 times as many dirty
tests (Boris Beizer in Johnson 1994).
我们编写的是一个被称为 happly test 的 case,因为我们接受了一个最为普通的 case,我们只能保证在一个非常适用的场景下的可靠性,而真正有经验的开发同学会需要增加更多的边界测试。
funcSplit(s, sep string) []string { var result []string i := strings.Index(s, sep) for i > -1 { result = append(result, s[:i]) s = s[i+len(sep):] i = strings.Index(s, sep) } returnappend(result, s) }
//passing value dari DataProvider ke parameter di method test @Test(dataProvider = "loginData") publicvoidlogin(String phoneEmail, String pass, String expected){ driver.findElement(By.id("email")).sendKeys(phoneEmail); driver.findElement(By.id("pass")).sendKeys(pass); driver.findElement(By.name("login")).click(); //compare expected result dengan actual result dari website if (expected.equals("failed_login")){ WebElementerrorBox= driver.findElement(By.id("error_box")); Assert.assertTrue(errorBox.isDisplayed()); } elseif (expected.equals("success_login")){ WebElementsearchBox= driver.findElement(By.xpath("//input[@aria-label = 'Cari di Facebook']")); Assert.assertTrue(searchBox.isDisplayed()); } }
@DataProvider public Object[][] loginData(){ return File.ReadAll("/example.json") }
//passing value dari DataProvider ke parameter di method test @Test(dataProvider = "loginData") publicvoidlogin(String phoneEmail, String pass, String expected){ driver.findElement(By.id("email")).sendKeys(phoneEmail); driver.findElement(By.id("pass")).sendKeys(pass); driver.findElement(By.name("login")).click(); //compare expected result dengan actual result dari website if (expected.equals("failed_login")){ WebElementerrorBox= driver.findElement(By.id("error_box")); Assert.assertTrue(errorBox.isDisplayed()); } elseif (expected.equals("success_login")){ WebElementsearchBox= driver.findElement(By.xpath("//input[@aria-label = 'Cari di Facebook']")); Assert.assertTrue(searchBox.isDisplayed()); } }
Describe("Checking books out of the library", Label("library"), func() { var library *libraries.Library var book *books.Book var valjean *users.User BeforeEach(func() { library = libraries.NewClient() book = &books.Book{ Title: "Les Miserables", Author: "Victor Hugo", } valjean = users.NewUser("Jean Valjean") })
When("the library has the book in question", func() { BeforeEach(func() { Expect(library.Store(book)).To(Succeed()) })
Context("and the book is available", func() { It("lends it to the reader", func() { Expect(valjean.Checkout(library, "Les Miserables")).To(Succeed()) Expect(valjean.Books()).To(ContainElement(book)) Expect(library.UserWithBook(book)).To(Equal(valjean)) }) })
Context("but the book has already been checked out", func() { var javert *users.User BeforeEach(func() { javert = users.NewUser("Javert") Expect(javert.Checkout(library, "Les Miserables")).To(Succeed()) })
It("tells the user", func() { err := valjean.Checkout(library, "Les Miserables") Expect(error).To(MatchError("Les Miserables is currently checked out")) })
It("lets the user place a hold and get notified later", func() { Expect(valjean.Hold(library, "Les Miserables")).To(Succeed()) Expect(valjean.Holds()).To(ContainElement(book))
By("when Javert returns the book") Expect(javert.Return(library, book)).To(Succeed())
By("it eventually informs Valjean") notification := "Les Miserables is ready for pick up" Eventually(valjean.Notifications).Should(ContainElement(notification))
When("the library does not have the book in question", func() { It("tells the reader the book is unavailable", func() { err := valjean.Checkout(library, "Les Miserables") Expect(error).To(MatchError("Les Miserables is not in the library catalog")) }) }) })
f// RegisterUser if the user is not registered before funcRegisterUser(user User)error { if userdb.UserExist(user.Email) { return fmt.Errorf("email '%s' already registered", user.Email) } // ...code for registering the user... log.Println(user) returnnil }
对于 Register 来说,我们主要逻辑并不是 Db 相关,因此,我们如果要去测试这个需要跑一个数据库,然后初始化系统很烦,因此,我们会选择将 userdb mock 掉。
funcbindingErrToStandardError(bindingErr *binding.Error) (standardError *errors.Error) { // binding err including missing param, parameter type err and so on // here we only handle missing param, other kind of err we all regard as // invalid param if bindingErr.ErrType == BindingErr && isMissingParamErr(bindingErr.Msg) { standardError = errors.ToCommonError(errors.MissingParameter_parameter(bindingErr.FailField)) } else { standardError = errors.ToCommonError(errors.InvalidParameter_parameter(bindingErr.FailField)) } return standardError }