Repository: bxcodec/faker
Pull request #43 (2019-01-13 05:06:02)

fix: custom provider generator
Proposed changes:
Now we can easily add our own custom faker-generator provider.
Example: 
```go
type Gondoruwo struct {
	Name       string
	Locatadata int
}

func CustomGenerator() {
	faker.AddProvider("customIdFaker", func(v reflect.Value) (interface{}, error) {
		 return int64(43), nil
	})
	faker.AddProvider("danger", func(v reflect.Value) (interface{}, error) {
		return "danger-ranger", nil
	})

	faker.AddProvider("gondoruwo", func(v reflect.Value) (interface{}, error) {
		obj := Gondoruwo{
			Name:       "Power",
			Locatadata: 324,
		}
		return obj, nil
	})
}

type Sample struct {
	ID                 int64     `faker:"customIdFaker"`
	Gondoruwo          Gondoruwo `faker:"gondoruwo"`
	Danger             string    `faker:"danger"`
}
```

Results:
```
{ID:43 Gondoruwo:{Name:Power Locatadata:324} Danger:danger-ranger}
```

codecov[bot]: # [Codecov](https://codecov.io/gh/bxcodec/faker/pull/43?src=pr&el=h1) Report
> Merging [#43](https://codecov.io/gh/bxcodec/faker/pull/43?src=pr&el=desc) into [master](https://codecov.io/gh/bxcodec/faker/commit/36687d344cfd03a7463e722d77a0a05a68c4f116?src=pr&el=desc) will **decrease** coverage by `2.84%`.
> The diff coverage is `92.16%`.

[![Impacted file tree graph](https://codecov.io/gh/bxcodec/faker/pull/43/graphs/tree.svg?width=650&token=cLPGB7MHVc&height=150&src=pr)](https://codecov.io/gh/bxcodec/faker/pull/43?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master      #43      +/-   ##
==========================================
- Coverage   98.12%   95.27%   -2.85%     
==========================================
  Files          10       10              
  Lines         426      529     +103     
==========================================
+ Hits          418      504      +86     
- Misses          4       17      +13     
- Partials        4        8       +4
```


| [Impacted Files](https://codecov.io/gh/bxcodec/faker/pull/43?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [datetime.go](https://codecov.io/gh/bxcodec/faker/pull/43/diff?src=pr&el=tree#diff-ZGF0ZXRpbWUuZ28=) | `100% <100%> (ø)` | :arrow_up: |
| [uuid.go](https://codecov.io/gh/bxcodec/faker/pull/43/diff?src=pr&el=tree#diff-dXVpZC5nbw==) | `100% <100%> (ø)` | :arrow_up: |
| [phone.go](https://codecov.io/gh/bxcodec/faker/pull/43/diff?src=pr&el=tree#diff-cGhvbmUuZ28=) | `100% <100%> (ø)` | :arrow_up: |
| [price.go](https://codecov.io/gh/bxcodec/faker/pull/43/diff?src=pr&el=tree#diff-cHJpY2UuZ28=) | `100% <100%> (ø)` | :arrow_up: |
| [payment.go](https://codecov.io/gh/bxcodec/faker/pull/43/diff?src=pr&el=tree#diff-cGF5bWVudC5nbw==) | `100% <100%> (ø)` | :arrow_up: |
| [address.go](https://codecov.io/gh/bxcodec/faker/pull/43/diff?src=pr&el=tree#diff-YWRkcmVzcy5nbw==) | `100% <100%> (ø)` | :arrow_up: |
| [person.go](https://codecov.io/gh/bxcodec/faker/pull/43/diff?src=pr&el=tree#diff-cGVyc29uLmdv) | `97.36% <100%> (-2.64%)` | :arrow_down: |
| [internet.go](https://codecov.io/gh/bxcodec/faker/pull/43/diff?src=pr&el=tree#diff-aW50ZXJuZXQuZ28=) | `100% <100%> (ø)` | :arrow_up: |
| [lorem.go](https://codecov.io/gh/bxcodec/faker/pull/43/diff?src=pr&el=tree#diff-bG9yZW0uZ28=) | `100% <100%> (ø)` | :arrow_up: |
| [faker.go](https://codecov.io/gh/bxcodec/faker/pull/43/diff?src=pr&el=tree#diff-ZmFrZXIuZ28=) | `87.5% <35%> (-7.96%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/bxcodec/faker/pull/43?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/bxcodec/faker/pull/43?src=pr&el=footer). Last update [36687d3...f13cbe9](https://codecov.io/gh/bxcodec/faker/pull/43?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/README.md b/README.md
index 9eba3f3..6fc5e52 100644
--- a/README.md
+++ b/README.md
@@ -34,9 +34,9 @@ See documentation in [Godoc](https://godoc.org/github.com/bxcodec/faker)
 ```shell
 go get -u github.com/bxcodec/faker
 ```
-## Example
+# Example
 
-### With Tag
+## With Tag
 Supported tag:
 
 **Internet :**
@@ -213,7 +213,52 @@ func main() {
 
 ```
 
-### Without Tag
+## Custom Generator Provider
+You can also add your own generator function to your own defined tags. See example below
+```go
+type Gondoruwo struct {
+	Name       string
+	Locatadata int
+}
+
+type Sample struct {
+	ID                 int64     `faker:"customIdFaker"`
+	Gondoruwo          Gondoruwo `faker:"gondoruwo"`
+	Danger             string    `faker:"danger"`
+}
+
+func CustomGenerator() {
+	faker.AddProvider("customIdFaker", func(v reflect.Value) (interface{}, error) {
+		 return int64(43), nil
+	})
+	faker.AddProvider("danger", func(v reflect.Value) (interface{}, error) {
+		return "danger-ranger", nil
+	})
+
+	faker.AddProvider("gondoruwo", func(v reflect.Value) (interface{}, error) {
+		obj := Gondoruwo{
+			Name:       "Power",
+			Locatadata: 324,
+		}
+		return obj, nil
+	})
+}
+
+func main() { 
+	CustomGenerator()
+	var sample Sample
+	faker.FakeData(&sample)
+	fmt.Printf("%+v", sample)
+}
+```
+
+Results:
+```
+{ID:43 Gondoruwo:{Name:Power Locatadata:324} Danger:danger-ranger}
+```
+
+## Without Tag
+You also can use faker to generate your structs data randomly without any tag. And it will fill the data based on its data-type.
 
 ```go
 
@@ -294,8 +339,11 @@ func main() {
 
 ```
 
+## DEMO
+
 ![Example to use Faker](https://cdn-images-1.medium.com/max/800/1*AkMbxngg7zfvtWiuvFb4Mg.gif)
 
+## Benchmark
 Bench To Generate Fake Data
 #### Without Tag
 ```bash
diff --git a/address.go b/address.go
index a7b561c..044fb08 100644
--- a/address.go
+++ b/address.go
@@ -25,35 +25,42 @@ func SetAddress(net Addresser) {
 
 // Addresser is logical layer for Address
 type Addresser interface {
-	Latitude(v reflect.Value) error
-	Longitude(v reflect.Value) error
+	Latitude(v reflect.Value) (interface{}, error)
+	Longitude(v reflect.Value) (interface{}, error)
 }
 
 // Address struct
 type Address struct{}
 
+func (i Address) latitute() float32 {
+	return (rand.Float32() * 180) - 90
+}
+
 // Latitude sets latitude of the address
-func (i Address) Latitude(v reflect.Value) error {
+func (i Address) Latitude(v reflect.Value) (interface{}, error) {
 	kind := v.Kind()
-	val := (rand.Float32() * 180) - 90
+	val := i.latitute()
 	if kind == reflect.Float32 {
 		v.Set(reflect.ValueOf(val))
-		return nil
+		return float32(val), nil
 	}
 	v.Set(reflect.ValueOf(float64(val)))
 
-	return nil
+	return float64(val), nil
+}
+
+func (i Address) longitude() float32 {
+	return (rand.Float32() * 360) - 180
 }
 
 // Longitude sets longitude of the address
-func (i Address) Longitude(v reflect.Value) error {
+func (i Address) Longitude(v reflect.Value) (interface{}, error) {
 	kind := v.Kind()
-	val := (rand.Float32() * 360) - 180
-
+	val := i.longitude()
 	if kind == reflect.Float32 {
 		v.Set(reflect.ValueOf(val))
-		return nil
+		return float32(val), nil
 	}
 	v.Set(reflect.ValueOf(float64(val)))
-	return nil
+	return float64(val), nil
 }
diff --git a/datetime.go b/datetime.go
index c02f53e..0065be7 100644
--- a/datetime.go
+++ b/datetime.go
@@ -607,17 +607,17 @@ const (
 
 // A DateTimer contains random Time generators, returning time string in certain particular format
 type DateTimer interface {
-	UnixTime(v reflect.Value) error
-	Date() string
-	Time() string
-	MonthName() string
-	Year() string
-	DayOfWeek() string
-	DayOfMonth() string
-	Timestamp() string
-	Century() string
-	TimeZone() string
-	TimePeriod() string
+	UnixTime(v reflect.Value) (interface{}, error)
+	Date(v reflect.Value) (interface{}, error)
+	Time(v reflect.Value) (interface{}, error)
+	MonthName(v reflect.Value) (interface{}, error)
+	Year(v reflect.Value) (interface{}, error)
+	DayOfWeek(v reflect.Value) (interface{}, error)
+	DayOfMonth(v reflect.Value) (interface{}, error)
+	Timestamp(v reflect.Value) (interface{}, error)
+	Century(v reflect.Value) (interface{}, error)
+	TimeZone(v reflect.Value) (interface{}, error)
+	TimePeriod(v reflect.Value) (interface{}, error)
 }
 
 var date DateTimer
@@ -642,68 +642,111 @@ func SetDateTimer(d DateTimer) {
 type DateTime struct {
 }
 
+func (d DateTime) unixtime() int64 {
+	return RandomUnixTime()
+}
+
 // UnixTime get unix time
-func (d DateTime) UnixTime(v reflect.Value) error {
+func (d DateTime) UnixTime(v reflect.Value) (interface{}, error) {
 	kind := v.Kind()
-
+	var val int64
 	if kind == reflect.Int64 {
-		v.SetInt(RandomUnixTime())
+		val = d.unixtime()
 	} else {
-		v.SetInt(0)
+		val = 0
 	}
-	return nil
+	v.SetInt(val)
+	return val, nil
 }
 
-// Date formats DateTime using example BaseDate const
-func (d DateTime) Date() string {
+func (d DateTime) date() string {
 	return time.Unix(RandomUnixTime(), 0).Format(BaseDate)
 }
 
-// Time formats DateTime using example Time const
-func (d DateTime) Time() string {
+// Date formats DateTime using example BaseDate const
+func (d DateTime) Date(v reflect.Value) (interface{}, error) {
+	return d.date(), nil
+}
+
+func (d DateTime) time() string {
 	return time.Unix(RandomUnixTime(), 0).Format(Time)
 }
 
-// MonthName formats DateTime using example Month const
-func (d DateTime) MonthName() string {
+// Time formats DateTime using example Time const
+func (d DateTime) Time(v reflect.Value) (interface{}, error) {
+	return d.time(), nil
+}
+
+func (d DateTime) monthName() string {
 	return time.Unix(RandomUnixTime(), 0).Format(Month)
 }
 
-// Year formats DateTime using example Year const
-func (d DateTime) Year() string {
+// MonthName formats DateTime using example Month const
+func (d DateTime) MonthName(v reflect.Value) (interface{}, error) {
+	return d.monthName(), nil
+}
+
+func (d DateTime) year() string {
 	return time.Unix(RandomUnixTime(), 0).Format(Year)
 }
 
-// DayOfWeek formats DateTime using example Day const
-func (d DateTime) DayOfWeek() string {
+// Year formats DateTime using example Year const
+func (d DateTime) Year(v reflect.Value) (interface{}, error) {
+	return d.year(), nil
+}
+func (d DateTime) dayOfWeek() string {
 	return time.Unix(RandomUnixTime(), 0).Format(Day)
 }
 
-// DayOfMonth formats DateTime using example DayOfMonth const
-func (d DateTime) DayOfMonth() string {
+// DayOfWeek formats DateTime using example Day const
+func (d DateTime) DayOfWeek(v reflect.Value) (interface{}, error) {
+	return d.dayOfWeek(), nil
+}
+
+func (d DateTime) dayOfMonth() string {
 	return time.Unix(RandomUnixTime(), 0).Format(DayOfMonth)
 }
 
-// Timestamp formats DateTime using example Timestamp const
-func (d DateTime) Timestamp() string {
+// DayOfMonth formats DateTime using example DayOfMonth const
+func (d DateTime) DayOfMonth(v reflect.Value) (interface{}, error) {
+	return d.dayOfMonth(), nil
+}
+
+func (d DateTime) timestamp() string {
 	return time.Unix(RandomUnixTime(), 0).Format(fmt.Sprintf("%s %s", BaseDate, Time))
 }
 
-// Century returns a random century
-func (d DateTime) Century() string {
+// Timestamp formats DateTime using example Timestamp const
+func (d DateTime) Timestamp(v reflect.Value) (interface{}, error) {
+	return d.timestamp(), nil
+}
+func (d DateTime) century() string {
 	return randomElementFromSliceString(century)
 }
 
-// TimeZone returns a random timezone
-func (d DateTime) TimeZone() string {
+// Century returns a random century
+func (d DateTime) Century(v reflect.Value) (interface{}, error) {
+	return d.century(), nil
+}
+
+func (d DateTime) timezone() string {
 	return randomElementFromSliceString(timezones)
 }
 
-// TimePeriod formats DateTime using example TimePeriod const
-func (d DateTime) TimePeriod() string {
+// TimeZone returns a random timezone
+func (d DateTime) TimeZone(v reflect.Value) (interface{}, error) {
+	return d.timezone(), nil
+}
+
+func (d DateTime) period() string {
 	return time.Unix(RandomUnixTime(), 0).Format(TimePeriod)
 }
 
+// TimePeriod formats DateTime using example TimePeriod const
+func (d DateTime) TimePeriod(v reflect.Value) (interface{}, error) {
+	return d.period(), nil
+}
+
 // RandomUnixTime is a helper function returning random Unix time
 func RandomUnixTime() int64 {
 	return rand.Int63n(time.Now().Unix())
diff --git a/faker.go b/faker.go
index 6438b5e..7321fe6 100644
--- a/faker.go
+++ b/faker.go
@@ -64,7 +64,10 @@ const (
 	SKIP               = "-"
 )
 
-var mapperTag = map[string]interface{}{
+// TaggedFunction ...
+type TaggedFunction func(v reflect.Value) (interface{}, error)
+
+var mapperTag = map[string]TaggedFunction{
 	Email:              GetNetworker().Email,
 	MacAddress:         GetNetworker().MacAddress,
 	DomainName:         GetNetworker().DomainName,
@@ -156,7 +159,7 @@ func FakeData(a interface{}) error {
 }
 
 // AddProvider extend faker with tag to generate fake data with specified custom algoritm
-func AddProvider(tag string, provider interface{}) error {
+func AddProvider(tag string, provider TaggedFunction) error {
 	if _, ok := mapperTag[tag]; ok {
 		return errors.New(ErrTagAlreadyExists)
 	}
@@ -297,6 +300,16 @@ func setDataWithTag(v reflect.Value, tag string) error {
 
 	case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int8, reflect.Int16:
 		return userDefinedInt(v, tag)
+	default:
+		if _, exist := mapperTag[tag]; !exist {
+			return errors.New(ErrTagNotSupported)
+		}
+		res, err := mapperTag[tag](v)
+		if err != nil {
+			return err
+		}
+		v.Set(reflect.ValueOf(res))
+
 	}
 	return nil
 }
@@ -305,7 +318,11 @@ func userDefinedFloat(v reflect.Value, tag string) error {
 	if _, exist := mapperTag[tag]; !exist {
 		return errors.New(ErrTagNotSupported)
 	}
-	mapperTag[tag].(func(v reflect.Value) error)(v)
+	res, err := mapperTag[tag](v)
+	if err != nil {
+		return err
+	}
+	v.Set(reflect.ValueOf(res))
 	return nil
 }
 
@@ -314,7 +331,11 @@ func userDefinedString(v reflect.Value, tag string) error {
 	if _, exist := mapperTag[tag]; !exist {
 		return errors.New(ErrTagNotSupported)
 	}
-	val = mapperTag[tag].(func() string)()
+	item, err := mapperTag[tag](v)
+	if err != nil {
+		return err
+	}
+	val, _ = item.(string)
 	v.SetString(val)
 	return nil
 }
@@ -323,7 +344,12 @@ func userDefinedInt(v reflect.Value, tag string) error {
 	if _, exist := mapperTag[tag]; !exist {
 		return errors.New(ErrTagNotSupported)
 	}
-	mapperTag[tag].(func(v reflect.Value) error)(v)
+	val, err := mapperTag[tag](v)
+	if err != nil {
+		return err
+	}
+
+	v.Set(reflect.ValueOf(val))
 	return nil
 }
 
diff --git a/internet.go b/internet.go
index df521cc..1cb17ec 100644
--- a/internet.go
+++ b/internet.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"math/rand"
 	"net"
+	"reflect"
 	"strings"
 )
 
@@ -42,26 +43,29 @@ func SetNetwork(net Networker) {
 
 // Networker is logical layer for Internet
 type Networker interface {
-	Email() string
-	MacAddress() string
-	DomainName() string
-	URL() string
-	UserName() string
-	IPv4() string
-	IPv6() string
-	Password() string
+	Email(v reflect.Value) (interface{}, error)
+	MacAddress(v reflect.Value) (interface{}, error)
+	DomainName(v reflect.Value) (interface{}, error)
+	URL(v reflect.Value) (interface{}, error)
+	UserName(v reflect.Value) (interface{}, error)
+	IPv4(v reflect.Value) (interface{}, error)
+	IPv6(v reflect.Value) (interface{}, error)
+	Password(v reflect.Value) (interface{}, error)
 }
 
 // Internet struct
 type Internet struct{}
 
-// Email generates random email id
-func (internet Internet) Email() string {
+func (internet Internet) email() string {
 	return randomString(7) + "@" + randomString(5) + "." + randomElementFromSliceString(tld)
 }
 
-// MacAddress generates random MacAddress
-func (internet Internet) MacAddress() string {
+// Email generates random email id
+func (internet Internet) Email(v reflect.Value) (interface{}, error) {
+	return internet.email(), nil
+}
+
+func (internet Internet) macAddress() string {
 	ip := make([]byte, 6)
 	for i := 0; i < 6; i++ {
 		ip[i] = byte(rand.Intn(256))
@@ -69,28 +73,44 @@ func (internet Internet) MacAddress() string {
 	return net.HardwareAddr(ip).String()
 }
 
-// DomainName generates random domain name
-func (internet Internet) DomainName() string {
+// MacAddress generates random MacAddress
+func (internet Internet) MacAddress(v reflect.Value) (interface{}, error) {
+	return internet.macAddress(), nil
+}
+
+func (internet Internet) domainName() string {
 	return randomString(7) + "." + randomElementFromSliceString(tld)
 }
 
-// URL generates random URL standardised in urlFormats const
-func (internet Internet) URL() string {
+// DomainName generates random domain name
+func (internet Internet) DomainName(v reflect.Value) (interface{}, error) {
+	return internet.domainName(), nil
+}
+
+func (internet Internet) url() string {
 	format := randomElementFromSliceString(urlFormats)
 	countVerbs := strings.Count(format, "%s")
 	if countVerbs == 1 {
-		return fmt.Sprintf(format, internet.DomainName())
+		return fmt.Sprintf(format, internet.domainName())
 	}
-	return fmt.Sprintf(format, internet.DomainName(), internet.UserName())
+	return fmt.Sprintf(format, internet.domainName(), internet.username())
 }
 
-// UserName generates random username
-func (internet Internet) UserName() string {
+// URL generates random URL standardised in urlFormats const
+func (internet Internet) URL(v reflect.Value) (interface{}, error) {
+	return internet.url(), nil
+}
+
+func (internet Internet) username() string {
 	return randomString(7)
 }
 
-// IPv4 generates random IPv4 address
-func (internet Internet) IPv4() string {
+// UserName generates random username
+func (internet Internet) UserName(v reflect.Value) (interface{}, error) {
+	return internet.username(), nil
+}
+
+func (internet Internet) ipv4() string {
 	size := 4
 	ip := make([]byte, size)
 	for i := 0; i < size; i++ {
@@ -99,8 +119,12 @@ func (internet Internet) IPv4() string {
 	return net.IP(ip).To4().String()
 }
 
-// IPv6 generates random IPv6 address
-func (internet Internet) IPv6() string {
+// IPv4 generates random IPv4 address
+func (internet Internet) IPv4(v reflect.Value) (interface{}, error) {
+	return internet.ipv4(), nil
+}
+
+func (internet Internet) ipv6() string {
 	size := 16
 	ip := make([]byte, size)
 	for i := 0; i < size; i++ {
@@ -109,7 +133,16 @@ func (internet Internet) IPv6() string {
 	return net.IP(ip).To16().String()
 }
 
-// Password returns a hashed password
-func (internet Internet) Password() string {
+// IPv6 generates random IPv6 address
+func (internet Internet) IPv6(v reflect.Value) (interface{}, error) {
+	return internet.ipv6(), nil
+}
+
+func (internet Internet) password() string {
 	return randomString(50)
 }
+
+// Password returns a hashed password
+func (internet Internet) Password(v reflect.Value) (interface{}, error) {
+	return internet.password(), nil
+}
diff --git a/lorem.go b/lorem.go
index 27ef5e5..8556160 100644
--- a/lorem.go
+++ b/lorem.go
@@ -3,6 +3,7 @@ package faker
 import (
 	"fmt"
 	"math/rand"
+	"reflect"
 	"strings"
 )
 
@@ -49,9 +50,9 @@ var wordList = []string{
 
 // DataFaker generates randomized Words, Sentences and Paragraphs
 type DataFaker interface {
-	Word() string
-	Sentence() string
-	Paragraph() string
+	Word(v reflect.Value) (interface{}, error)
+	Sentence(v reflect.Value) (interface{}, error)
+	Paragraph(v reflect.Value) (interface{}, error)
 }
 
 // SetDataFaker sets Custom data in lorem
@@ -74,13 +75,17 @@ func GetLorem() DataFaker {
 type Lorem struct {
 }
 
-// Word returns a word from the wordList const
-func (l Lorem) Word() string {
+func (l Lorem) word() string {
 	return randomElementFromSliceString(wordList)
 }
 
-// Sentence returns a sentence using the wordList const
-func (l Lorem) Sentence() (sentence string) {
+// Word returns a word from the wordList const
+func (l Lorem) Word(v reflect.Value) (interface{}, error) {
+	return l.word(), nil
+}
+
+func (l Lorem) sentence() string {
+	sentence := ""
 	r, _ := RandomInt(1, 6)
 	size := len(r)
 	for key, val := range r {
@@ -96,14 +101,25 @@ func (l Lorem) Sentence() (sentence string) {
 	return fmt.Sprintf("%s.", sentence)
 }
 
-// Paragraph returns a series of sentences as a paragraph using the wordList const
-func (l Lorem) Paragraph() (paragraph string) {
+// Sentence returns a sentence using the wordList const
+func (l Lorem) Sentence(v reflect.Value) (interface{}, error) {
+	sentence := l.sentence()
+	return sentence, nil
+}
+
+func (l Lorem) paragraph() string {
+	paragraph := ""
 	size := rand.Intn(10) + 1
 	for i := 0; i < size; i++ {
-		paragraph += l.Sentence()
+		paragraph += l.sentence()
 		if i != size-1 {
 			paragraph += " "
 		}
 	}
 	return paragraph
 }
+
+// Paragraph returns a series of sentences as a paragraph using the wordList const
+func (l Lorem) Paragraph(v reflect.Value) (interface{}, error) {
+	return l.paragraph(), nil
+}
diff --git a/payment.go b/payment.go
index 31b73e4..6659128 100644
--- a/payment.go
+++ b/payment.go
@@ -2,8 +2,8 @@ package faker
 
 import (
 	"math/rand"
+	"reflect"
 	"strconv"
-	"strings"
 )
 
 const (
@@ -22,6 +22,10 @@ var creditCards = map[string]creditCard{
 	"mastercard":       {"MasterCard", 16, []int{51, 52, 53, 54, 55}},
 	"american express": {"American Express", 15, []int{34, 37}},
 	"discover":         {"Discover", 16, []int{6011}},
+	"VISA":             {"VISA", 16, []int{4539, 4556, 4916, 4532, 4929, 40240071, 4485, 4716, 4}},
+	"MasterCard":       {"MasterCard", 16, []int{51, 52, 53, 54, 55}},
+	"American Express": {"American Express", 15, []int{34, 37}},
+	"Discover":         {"Discover", 16, []int{6011}},
 }
 
 var pay Render
@@ -46,16 +50,14 @@ func SetPayment(p Render) {
 
 // Render contains Whole Random Credit Card Generators with their types
 type Render interface {
-	CreditCardType() string
-	CreditCardNumber() string
+	CreditCardType(v reflect.Value) (interface{}, error)
+	CreditCardNumber(v reflect.Value) (interface{}, error)
 }
 
 // Payment struct
 type Payment struct{}
 
-// CreditCardType returns one of the following credit values:
-// VISA, MasterCard, American Express and Discover
-func (p Payment) CreditCardType() string {
+func (p Payment) cctype() string {
 	n := len(creditCards)
 	if cacheCreditCard != "" {
 		return cacheCreditCard
@@ -69,9 +71,14 @@ func (p Payment) CreditCardType() string {
 	return cacheCreditCard
 }
 
-// CreditCardNumber generated credit card number according to the card number rules
-func (p Payment) CreditCardNumber() string {
-	ccType := strings.ToLower(p.CreditCardType())
+// CreditCardType returns one of the following credit values:
+// VISA, MasterCard, American Express and Discover
+func (p Payment) CreditCardType(v reflect.Value) (interface{}, error) {
+	return p.cctype(), nil
+}
+
+func (p Payment) ccnumber() string {
+	ccType := p.cctype()
 	cacheCreditCard = ccType
 	card := creditCards[ccType]
 	prefix := strconv.Itoa(card.prefixes[rand.Intn(len(card.prefixes))])
@@ -82,3 +89,8 @@ func (p Payment) CreditCardNumber() string {
 	num += digit
 	return num
 }
+
+// CreditCardNumber generated credit card number according to the card number rules
+func (p Payment) CreditCardNumber(v reflect.Value) (interface{}, error) {
+	return p.ccnumber(), nil
+}
diff --git a/person.go b/person.go
index e7fe80a..5365379 100644
--- a/person.go
+++ b/person.go
@@ -3,17 +3,18 @@ package faker
 import (
 	"fmt"
 	"math/rand"
+	"reflect"
 )
 
 // Dowser provides interfaces to generate random logical Names with their initials
 type Dowser interface {
-	TitleMale() string
-	TitleFeMale() string
-	FirstName() string
-	FirstNameMale() string
-	FirstNameFemale() string
-	LastName() string
-	Name() string
+	TitleMale(v reflect.Value) (interface{}, error)
+	TitleFeMale(v reflect.Value) (interface{}, error)
+	FirstName(v reflect.Value) (interface{}, error)
+	FirstNameMale(v reflect.Value) (interface{}, error)
+	FirstNameFemale(v reflect.Value) (interface{}, error)
+	LastName(v reflect.Value) (interface{}, error)
+	Name(v reflect.Value) (interface{}, error)
 }
 
 var person Dowser
@@ -127,40 +128,68 @@ func SetDowser(d Dowser) {
 type Person struct {
 }
 
-// TitleMale generates random titles for males
-func (p Person) TitleMale() string {
+func (p Person) titlemale() string {
 	return randomElementFromSliceString(titlesMale)
 }
 
-// TitleFeMale generates random titles for females
-func (p Person) TitleFeMale() string {
+// TitleMale generates random titles for males
+func (p Person) TitleMale(v reflect.Value) (interface{}, error) {
+	return p.titlemale(), nil
+}
+
+func (p Person) titleFemale() string {
 	return randomElementFromSliceString(titlesFemale)
 }
 
-// FirstName retuns first names
-func (p Person) FirstName() string {
+// TitleFeMale generates random titles for females
+func (p Person) TitleFeMale(v reflect.Value) (interface{}, error) {
+	return p.titleFemale(), nil
+}
+
+func (p Person) firstname() string {
 	return randomElementFromSliceString(firstNames)
 }
 
-// FirstNameMale retuns first names for males
-func (p Person) FirstNameMale() string {
+// FirstName retuns first names
+func (p Person) FirstName(v reflect.Value) (interface{}, error) {
+	return p.firstname(), nil
+}
+
+func (p Person) firstnamemale() string {
 	return randomElementFromSliceString(firstNamesMale)
 }
 
-// FirstNameFemale retuns first names for females
-func (p Person) FirstNameFemale() string {
+// FirstNameMale retuns first names for males
+func (p Person) FirstNameMale(v reflect.Value) (interface{}, error) {
+	return p.firstnamemale(), nil
+}
+
+func (p Person) firstnamefemale() string {
 	return randomElementFromSliceString(firstNamesFemale)
 }
 
-// LastName returns last name
-func (p Person) LastName() string {
+// FirstNameFemale retuns first names for females
+func (p Person) FirstNameFemale(v reflect.Value) (interface{}, error) {
+	return p.firstnamefemale(), nil
+}
+
+func (p Person) lastname() string {
 	return randomElementFromSliceString(lastNames)
 }
 
-// Name returns a random name
-func (p Person) Name() string {
+// LastName returns last name
+func (p Person) LastName(v reflect.Value) (interface{}, error) {
+	return p.lastname(), nil
+}
+
+func (p Person) name() string {
 	if randNameFlag > 50 {
 		return fmt.Sprintf("%s %s %s", randomElementFromSliceString(titlesFemale), randomElementFromSliceString(firstNamesFemale), randomElementFromSliceString(lastNames))
 	}
 	return fmt.Sprintf("%s %s %s", randomElementFromSliceString(titlesMale), randomElementFromSliceString(firstNamesMale), randomElementFromSliceString(lastNames))
 }
+
+// Name returns a random name
+func (p Person) Name(v reflect.Value) (interface{}, error) {
+	return p.name(), nil
+}
diff --git a/phone.go b/phone.go
index 1e68ad6..1a27c7e 100644
--- a/phone.go
+++ b/phone.go
@@ -3,6 +3,7 @@ package faker
 import (
 	"fmt"
 	"math/rand"
+	"reflect"
 	"strings"
 
 	"github.com/bxcodec/faker/support/slice"
@@ -28,24 +29,27 @@ func SetPhoner(p Phoner) {
 
 // Phoner serves overall tele-phonic contact generator
 type Phoner interface {
-	PhoneNumber() string
-	TollFreePhoneNumber() string
-	E164PhoneNumber() string
+	PhoneNumber(v reflect.Value) (interface{}, error)
+	TollFreePhoneNumber(v reflect.Value) (interface{}, error)
+	E164PhoneNumber(v reflect.Value) (interface{}, error)
 }
 
 // Phone struct
 type Phone struct {
 }
 
-// PhoneNumber generates phone numbers of type: "201-886-0269"
-func (p Phone) PhoneNumber() string {
+func (p Phone) phonenumber() string {
 	randInt, _ := RandomInt(1, 10)
 	str := strings.Join(slice.IntToString(randInt), "")
 	return fmt.Sprintf("%s-%s-%s", str[:3], str[3:6], str[6:10])
 }
 
-// TollFreePhoneNumber generates phone numbers of type: "(888) 937-7238"
-func (p Phone) TollFreePhoneNumber() string {
+// PhoneNumber generates phone numbers of type: "201-886-0269"
+func (p Phone) PhoneNumber(v reflect.Value) (interface{}, error) {
+	return p.phonenumber(), nil
+}
+
+func (p Phone) tollfreephonenumber() string {
 	out := ""
 	boxDigitsStart := []string{"777", "888"}
 
@@ -59,8 +63,12 @@ func (p Phone) TollFreePhoneNumber() string {
 	return fmt.Sprintf("(%s) %s", boxDigitsStart[rand.Intn(1)], out)
 }
 
-// E164PhoneNumber generates phone numbers of type: "+27113456789"
-func (p Phone) E164PhoneNumber() string {
+// TollFreePhoneNumber generates phone numbers of type: "(888) 937-7238"
+func (p Phone) TollFreePhoneNumber(v reflect.Value) (interface{}, error) {
+	return p.tollfreephonenumber(), nil
+}
+
+func (p Phone) e164PhoneNumber() string {
 	out := ""
 	boxDigitsStart := []string{"7", "8"}
 	ints, _ := RandomInt(1, 10)
@@ -70,3 +78,8 @@ func (p Phone) E164PhoneNumber() string {
 	}
 	return fmt.Sprintf("+%s%s", boxDigitsStart[rand.Intn(1)], strings.Join(slice.IntToString(ints), ""))
 }
+
+// E164PhoneNumber generates phone numbers of type: "+27113456789"
+func (p Phone) E164PhoneNumber(v reflect.Value) (interface{}, error) {
+	return p.e164PhoneNumber(), nil
+}
diff --git a/price.go b/price.go
index 5ae3363..db51f2d 100644
--- a/price.go
+++ b/price.go
@@ -33,9 +33,9 @@ var currencies = []string{
 
 // Money provides an interface to generate a custom price with or without a random currency code
 type Money interface {
-	Currency() string
-	Amount(v reflect.Value) error
-	AmountWithCurrency() string
+	Currency(v reflect.Value) (interface{}, error)
+	Amount(v reflect.Value) (interface{}, error)
+	AmountWithCurrency(v reflect.Value) (interface{}, error)
 }
 
 // Price struct
@@ -60,28 +60,40 @@ func SetPrice(p Money) {
 	pri = p
 }
 
-// Currency returns a random currency from currencies
-func (p Price) Currency() string {
+func (p Price) currency() string {
 	return randomElementFromSliceString(currencies)
 }
 
+// Currency returns a random currency from currencies
+func (p Price) Currency(v reflect.Value) (interface{}, error) {
+	return p.currency(), nil
+}
+
+func (p Price) amount() float64 {
+	return precision(rand.Float64()*math.Pow10(rand.Intn(8)), rand.Intn(2)+1)
+}
+
 // Amount returns a random floating price amount
 // with a random precision of [1,2] up to (10**8 - 1)
-func (p Price) Amount(v reflect.Value) error {
+func (p Price) Amount(v reflect.Value) (interface{}, error) {
 	kind := v.Kind()
-	val := precision(rand.Float64()*math.Pow10(rand.Intn(8)), rand.Intn(2)+1)
+	val := p.amount()
 	if kind == reflect.Float32 {
 		v.Set(reflect.ValueOf(float32(val)))
-		return nil
+		return float32(val), nil
 	}
 	v.Set(reflect.ValueOf(val))
-	return nil
+	return val, nil
+}
+
+func (p Price) amountwithcurrency() string {
+	val := p.amount()
+	return fmt.Sprintf("%s %f", p.currency(), val)
 }
 
 // AmountWithCurrency combines both price and currency together
-func (p Price) AmountWithCurrency() string {
-	val := precision(rand.Float64()*math.Pow10(rand.Intn(8)), rand.Intn(2)+1)
-	return fmt.Sprintf("%s %f", p.Currency(), val)
+func (p Price) AmountWithCurrency(v reflect.Value) (interface{}, error) {
+	return p.amountwithcurrency(), nil
 }
 
 // precision | a helper function to set precision of price
diff --git a/uuid.go b/uuid.go
index e260da8..04081f3 100644
--- a/uuid.go
+++ b/uuid.go
@@ -4,6 +4,7 @@ import (
 	"crypto/rand"
 	"fmt"
 	"io"
+	"reflect"
 )
 
 var identifier Identifier
@@ -21,8 +22,8 @@ func GetIdentifier() Identifier {
 
 // Identifier ...
 type Identifier interface {
-	Digit() string
-	Hyphenated() string
+	Digit(v reflect.Value) (interface{}, error)
+	Hyphenated(v reflect.Value) (interface{}, error)
 }
 
 // UUID struct
@@ -39,16 +40,25 @@ func createUUID() []byte {
 	return b
 }
 
-// Hyphenated returns a 36 byte hyphenated UUID
-func (i UUID) Hyphenated() string {
+func (u UUID) hyphenated() string {
 	b := createUUID()
 	uuid := fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
 	return uuid
 }
 
-// Digit returns a 32 bytes UUID
-func (i UUID) Digit() string {
+// Hyphenated returns a 36 byte hyphenated UUID
+func (i UUID) Hyphenated(v reflect.Value) (interface{}, error) {
+	return i.hyphenated(), nil
+}
+
+func (u UUID) digit() string {
 	b := createUUID()
 	uuid := fmt.Sprintf("%x", b)
 	return uuid
 }
+
+// Digit returns a 32 bytes UUID
+func (i UUID) Digit(v reflect.Value) (interface{}, error) {
+
+	return i.digit(), nil
+}


Test patch:
diff --git a/datetime_test.go b/datetime_test.go
index a7edc14..ce15d43 100644
--- a/datetime_test.go
+++ b/datetime_test.go
@@ -43,7 +43,11 @@ func TestUnixTimeValueNotValid(t *testing.T) {
 
 func TestDate(t *testing.T) {
 	d := GetDateTimer()
-	_, err := time.Parse(BaseDate, d.Date())
+	date, err := d.Date(reflect.Value{})
+	if err != nil {
+		t.Error("function Date need return valid value")
+	}
+	_, err = time.Parse(BaseDate, date.(string))
 
 	if err != nil {
 		t.Error("function Date need return valid value")
@@ -52,8 +56,11 @@ func TestDate(t *testing.T) {
 
 func TestTime(t *testing.T) {
 	d := GetDateTimer()
-	_, err := time.Parse(Time, d.Time())
-
+	tm, err := d.Time(reflect.Value{})
+	if err != nil {
+		t.Error("function Time need return valid value")
+	}
+	_, err = time.Parse(Time, tm.(string))
 	if err != nil {
 		t.Error("function Time need return valid value")
 	}
@@ -61,7 +68,11 @@ func TestTime(t *testing.T) {
 
 func TestMonthName(t *testing.T) {
 	d := GetDateTimer()
-	_, err := time.Parse(Month, d.MonthName())
+	mt, err := d.MonthName(reflect.Value{})
+	if err != nil {
+		t.Error("function Month need return valid month")
+	}
+	_, err = time.Parse(Month, mt.(string))
 	if err != nil {
 		t.Error("function Month need return valid month")
 	}
@@ -69,7 +80,11 @@ func TestMonthName(t *testing.T) {
 
 func TestYear(t *testing.T) {
 	d := GetDateTimer()
-	_, err := time.Parse(Year, d.Year())
+	year, err := d.Year(reflect.Value{})
+	if err != nil {
+		t.Error("function Year need return valid year")
+	}
+	_, err = time.Parse(Year, year.(string))
 	if err != nil {
 		t.Error("function Year need return valid year")
 	}
@@ -77,7 +92,11 @@ func TestYear(t *testing.T) {
 
 func TestDayOfWeek(t *testing.T) {
 	d := GetDateTimer()
-	_, err := time.Parse(Day, d.DayOfWeek())
+	week, err := d.DayOfWeek(reflect.Value{})
+	if err != nil {
+		t.Error("function DayOfWeek need return valid day")
+	}
+	_, err = time.Parse(Day, week.(string))
 	if err != nil {
 		t.Error("function DayOfWeek need return valid day")
 	}
@@ -87,12 +106,15 @@ func TestDayOfWeekReturnsDifferentValues(t *testing.T) {
 	dayMap := make(map[string]struct{})
 	iterations := 5 // sufficiently large to assure we don't randomly get the same value again
 	for i := 0; i < iterations; i++ {
-		day := GetDateTimer().DayOfWeek()
-		if _, ok := dayMap[day]; ok {
+		day, err := GetDateTimer().DayOfWeek(reflect.Value{})
+		if err != nil {
+			t.Error("function DayOfWeek need return valid day")
+		}
+		if _, ok := dayMap[day.(string)]; ok {
 			i--
 			continue
 		}
-		dayMap[day] = struct{}{}
+		dayMap[day.(string)] = struct{}{}
 		t.Log(day) // Will print random and different day 5 times.
 	}
 
@@ -104,7 +126,11 @@ func TestDayOfWeekReturnsDifferentValues(t *testing.T) {
 
 func TestDayOfMonth(t *testing.T) {
 	d := GetDateTimer()
-	_, err := time.Parse(DayOfMonth, d.DayOfMonth())
+	mt, err := d.DayOfMonth(reflect.Value{})
+	if err != nil {
+		t.Error("function DayOfMonth need return valid digit")
+	}
+	_, err = time.Parse(DayOfMonth, mt.(string))
 	if err != nil {
 		t.Error("function DayOfMonth need return valid digit")
 	}
@@ -112,7 +138,11 @@ func TestDayOfMonth(t *testing.T) {
 
 func TestTimestamp(t *testing.T) {
 	d := GetDateTimer()
-	_, err := time.Parse(fmt.Sprintf("%s %s", BaseDate, Time), d.Timestamp())
+	tstmp, err := d.Timestamp(reflect.Value{})
+	if err != nil {
+		t.Error("function Timestamp need return valid timestamp format")
+	}
+	_, err = time.Parse(fmt.Sprintf("%s %s", BaseDate, Time), tstmp.(string))
 	if err != nil {
 		t.Error("function Timestamp need return valid timestamp format")
 	}
@@ -120,22 +150,33 @@ func TestTimestamp(t *testing.T) {
 
 func TestCentury(t *testing.T) {
 	d := GetDateTimer()
-
-	if !slice.Contains(century, d.Century()) {
+	centry, err := d.Century(reflect.Value{})
+	if err != nil {
+		t.Error("Expected century from functuon Century")
+	}
+	if !slice.Contains(century, centry.(string)) {
 		t.Error("Expected century from functuon Century")
 	}
 }
 
 func TestTimeZone(t *testing.T) {
 	d := GetDateTimer()
-	if !slice.Contains(timezones, d.TimeZone()) {
+	tz, err := d.TimeZone(reflect.Value{})
+	if err != nil {
+		t.Error("Expected timezone from variable timezones")
+	}
+	if !slice.Contains(timezones, tz.(string)) {
 		t.Error("Expected timezone from variable timezones")
 	}
 }
 
 func TestTimePeriod(t *testing.T) {
 	d := GetDateTimer()
-	_, err := time.Parse(TimePeriod, d.TimePeriod())
+	periode, err := d.TimePeriod(reflect.Value{})
+	if err != nil {
+		t.Error("function TimePeriod need return valid period")
+	}
+	_, err = time.Parse(TimePeriod, periode.(string))
 	if err != nil {
 		t.Error("function TimePeriod need return valid period")
 	}
diff --git a/faker_test.go b/faker_test.go
index 34de8cd..bf103b4 100644
--- a/faker_test.go
+++ b/faker_test.go
@@ -27,7 +27,7 @@ type SomeStruct struct {
 	LATITUDE           float64 `faker:"lat"`
 	Long               float32 `faker:"long"`
 	LONG               float64 `faker:"long"`
-	String             string
+	StringValue        string
 	CreditCardType     string `faker:"cc_type"`
 	CreditCardNumber   string `faker:"cc_number"`
 	Email              string `faker:"email"`
@@ -56,6 +56,67 @@ type SomeStruct struct {
 	MapStringStruct        map[string]AStruct
 	MapStringStructPointer map[string]*AStruct
 }
+
+func (s SomeStruct) String() string {
+	return fmt.Sprintf(`{
+	Inta: %v
+	Int8: %v
+	Int16: %v
+	Int32: %v
+	Int64: %v
+	Float32: %v
+	Float64: %v
+
+	UInta: %v
+	UInt8: %v
+	UInt16: %v
+	UInt32: %v
+	UInt64: %v
+
+	Latitude: %v
+	LATITUDE: %v
+	Long: %v
+	LONG: %v
+	StringValue: %v
+	CreditCardType: %v
+	CreditCardNumber: %v
+	Email: %v
+	IPV4: %v
+	IPV6: %v
+	Bool: %v
+	SString: %v
+	SInt: %v
+	SInt8: %v
+	SInt16: %v
+	SInt32: %v
+	SInt64: %v
+	SFloat32: %v
+	SFloat64:%v
+	SBool: %v
+	Struct: %v
+	Time: %v 
+	Stime: %v
+	Currency: %v
+	Amount: %v
+	AmountWithCurrency: %v
+	ID: %v
+	HyphenatedID: %v
+
+	MapStringString: %v
+	MapStringStruct: %v 
+	MapStringStructPointer: %v
+	}`, s.Inta, s.Int8, s.Int16, s.Int32,
+		s.Int64, s.Float32, s.Float64, s.UInta,
+		s.UInt8, s.UInt16, s.UInt32, s.UInt64,
+		s.Latitude, s.LATITUDE, s.Long, s.LONG,
+		s.StringValue, s.CreditCardType, s.CreditCardNumber,
+		s.Email, s.IPV4, s.IPV6, s.Bool, s.SString, s.SInt,
+		s.SInt8, s.SInt16, s.SInt32, s.SInt64, s.SFloat32, s.SFloat64,
+		s.SBool, s.Struct, s.Time, s.Stime, s.Currency, s.Amount,
+		s.AmountWithCurrency, s.ID, s.HyphenatedID, s.MapStringString,
+		s.MapStringStruct, s.MapStringStructPointer)
+}
+
 type AStruct struct {
 	Number        int64
 	Height        int64
@@ -252,33 +313,11 @@ func TestSetDataErrorDataParseTagIntType(t *testing.T) {
 
 func TestSetDataWithTagIfFirstArgumentNotPtr(t *testing.T) {
 	temp := struct{}{}
-	if "Not a pointer value" != setDataWithTag(reflect.ValueOf(temp), "").Error() {
+	if setDataWithTag(reflect.ValueOf(temp), "").Error() != "Not a pointer value" {
 		t.Error("Expected in arguments not ptr")
 	}
 }
 
-func TestSetDataWithTagIfFirstArgumentSlice(t *testing.T) {
-	temp := []int{}
-	if setDataWithTag(reflect.ValueOf(&temp), "") != nil {
-		t.Error("Not expected errors if first argument slice type")
-	}
-}
-
-func TestSetDataWithTagIfFirstArgumentNotFound(t *testing.T) {
-	temp := struct{}{}
-	if setDataWithTag(reflect.ValueOf(&temp), "") != nil {
-		t.Error("First argument is struct type, expected return nil")
-	}
-}
-
-func TestUserDefinedFloatNotFoundTag(t *testing.T) {
-	temp := struct{}{}
-
-	if userDefinedFloat(reflect.ValueOf(&temp), "") == nil {
-		t.Error("Not expected errors")
-	}
-}
-
 func BenchmarkFakerDataNOTTagged(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		a := NotTaggedStruct{}
@@ -434,36 +473,75 @@ func TestSkipField(t *testing.T) {
 
 }
 
+type Student struct {
+	Name   string
+	School School `faker:"custom-school"`
+}
+type School struct {
+	Location string
+}
+
 func TestExtend(t *testing.T) {
 	// This test is to ensure that faker can be extended new providers
 
-	a := struct {
-		ID string `faker:"test"`
-	}{}
+	t.Run("test-string", func(t *testing.T) {
+		a := struct {
+			ID string `faker:"test"`
+		}{}
+
+		err := AddProvider("test", func(v reflect.Value) (interface{}, error) {
+			return "test", nil
+		})
+
+		if err != nil {
+			t.Error("Expected Not Error, But Got: ", err)
+		}
+
+		err = FakeData(&a)
+
+		if err != nil {
+			t.Error("Expected Not Error, But Got: ", err)
+		}
 
-	err := AddProvider("test", func() string {
-		return "test"
+		if a.ID != "test" {
+			t.Error("ID should be equal test value")
+		}
 	})
 
-	if err != nil {
-		t.Error("Expected Not Error, But Got: ", err)
-	}
+	t.Run("test-struct", func(t *testing.T) {
+		a := &Student{}
+		err := AddProvider("custom-school", func(v reflect.Value) (interface{}, error) {
 
-	err = FakeData(&a)
+			sch := School{
+				Location: "North Kindom",
+			}
 
-	if err != nil {
-		t.Error("Expected Not Error, But Got: ", err)
-	}
+			return sch, nil
+		})
+
+		if err != nil {
+			t.Error("Expected Not Error, But Got: ", err)
+		}
+
+		err = FakeData(&a)
+
+		if err != nil {
+			t.Error("Expected Not Error, But Got: ", err)
+		}
+
+		if a.School.Location != "North Kindom" {
+			t.Error("ID should be equal test value")
+		}
+	})
 
-	if a.ID != "test" {
-		t.Error("ID should be equal test value")
-	}
 }
 
 func TestTagAlreadyExists(t *testing.T) {
 	// This test is to ensure that existing tag cannot be rewritten
 
-	err := AddProvider(Email, func() {})
+	err := AddProvider(Email, func(v reflect.Value) (interface{}, error) {
+		return nil, nil
+	})
 
 	if err == nil || err.Error() != ErrTagAlreadyExists {
 		t.Error("Expected ErrTagAlreadyExists Error,  But Got: ", err)
diff --git a/internet_test.go b/internet_test.go
index ca12193..9b8732c 100644
--- a/internet_test.go
+++ b/internet_test.go
@@ -1,6 +1,7 @@
 package faker
 
 import (
+	"reflect"
 	"strings"
 	"testing"
 
@@ -8,19 +9,32 @@ import (
 )
 
 func TestEmail(t *testing.T) {
-	if !strings.Contains(GetNetworker().Email(), "@") {
+	email, err := GetNetworker().Email(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if !strings.Contains(email.(string), "@") {
 		t.Error("Expected  email")
 	}
 }
 func TestMacAddress(t *testing.T) {
 	i := Internet{}
+	mc, err := i.MacAddress(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
 
-	if strings.Count(i.MacAddress(), ":") != 5 {
+	if strings.Count(mc.(string), ":") != 5 {
 		t.Error("Expected mac address")
 	}
 }
 func TestDomainName(t *testing.T) {
-	preTld := strings.Split(GetNetworker().DomainName(), ".")
+	domain, err := GetNetworker().DomainName(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+
+	preTld := strings.Split(domain.(string), ".")
 
 	if !slice.Contains(tld, preTld[1]) {
 		t.Error("Expected get DomainName")
@@ -29,41 +43,64 @@ func TestDomainName(t *testing.T) {
 func TestURLOneVerbs(t *testing.T) {
 	urlFormats = []string{
 		"http://www.%s/"}
-
-	if !strings.Contains(GetNetworker().URL(), "http") {
+	res, err := GetNetworker().URL(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if !strings.Contains(res.(string), "http") {
 		t.Error("Expected get url")
 	}
 }
 func TestURLTwoVerbs(t *testing.T) {
 	urlFormats = []string{
 		"http://www.%s/%s"}
-
-	if !strings.Contains(GetNetworker().URL(), "http") {
+	res, err := GetNetworker().URL(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if !strings.Contains(res.(string), "http") {
 		t.Error("Expected get url")
 	}
 }
 func TestUserName(t *testing.T) {
-	if GetNetworker().UserName() == "" {
+	usrname, err := GetNetworker().UserName(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if usrname.(string) == "" {
 		t.Error("Expected get username")
 	}
 
 }
 func TestIPv4(t *testing.T) {
-	if strings.Count(GetNetworker().IPv4(), ".") != 3 {
+	ip, err := GetNetworker().IPv4(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if strings.Count(ip.(string), ".") != 3 {
 		t.Error("Expected IPv4 format")
 	}
 }
 func TestIPv6(t *testing.T) {
-	if strings.Count(GetNetworker().IPv6(), ":") != 7 {
+	ip, err := GetNetworker().IPv6(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if strings.Count(ip.(string), ":") != 7 {
 		t.Error("Expected IPv4 format")
 	}
 }
 func TestSetNetwork(t *testing.T) {
+
 	SetNetwork(Internet{})
 }
 
 func TestPassword(t *testing.T) {
-	if GetNetworker().Password() == "" {
+	pass, err := GetNetworker().Password(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if pass.(string) == "" {
 		t.Error("Expected hash password")
 	}
 }
diff --git a/lorem_test.go b/lorem_test.go
index 91c5555..c954700 100644
--- a/lorem_test.go
+++ b/lorem_test.go
@@ -1,6 +1,8 @@
 package faker
 
 import (
+	"fmt"
+	"reflect"
 	"strings"
 	"testing"
 
@@ -12,20 +14,33 @@ func TestDataFaker(t *testing.T) {
 }
 
 func TestWord(t *testing.T) {
-	if !slice.Contains(wordList, GetLorem().Word()) {
+	word, err := GetLorem().Word(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if !slice.Contains(wordList, word.(string)) {
 		t.Error("Expected word from slice wordList")
 	}
 }
 
 func TestSentence(t *testing.T) {
-	s := GetLorem().Sentence()
+	res, err := GetLorem().Sentence(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	s := res.(string)
 	if s == "" || !strings.HasSuffix(s, ".") {
 		t.Error("Expected sentence")
 	}
 }
 
 func TestParagraph(t *testing.T) {
-	s := GetLorem().Paragraph()
+	res, err := GetLorem().Paragraph(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	s := res.(string)
+	fmt.Println(s)
 	if s == "" || !strings.HasSuffix(s, ".") {
 		t.Error("Expected paragraph")
 	}
diff --git a/payment_test.go b/payment_test.go
index 25c75c0..c28ebeb 100644
--- a/payment_test.go
+++ b/payment_test.go
@@ -1,19 +1,25 @@
 package faker
 
 import (
+	"reflect"
 	"strings"
 	"testing"
 )
 
 func TestCreditCardType(t *testing.T) {
-	randCC := strings.ToLower(GetPayment().CreditCardType())
+	ccType, err := GetPayment().CreditCardType(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	randCC := strings.ToLower(ccType.(string))
+
 	if _, exist := creditCards[randCC]; !exist {
 		t.Errorf("Expected from function creditCardType() : %s", randCC)
 	}
 }
 
 func TestCreditCardNumber(t *testing.T) {
-	GetPayment().CreditCardNumber()
+	GetPayment().CreditCardNumber(reflect.Value{})
 }
 
 func TestSetPayment(t *testing.T) {
diff --git a/person_test.go b/person_test.go
index 8435cc5..894f732 100644
--- a/person_test.go
+++ b/person_test.go
@@ -1,6 +1,7 @@
 package faker
 
 import (
+	"reflect"
 	"testing"
 
 	"github.com/bxcodec/faker/support/slice"
@@ -11,58 +12,82 @@ func TestSetDowser(t *testing.T) {
 }
 
 func TestTitleMale(t *testing.T) {
-	p := GetPerson()
-	if !slice.Contains(titlesMale, p.TitleMale()) {
+	male, err := GetPerson().TitleMale(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if !slice.Contains(titlesMale, male.(string)) {
 		t.Error("Expected value from variable titleMales in function TitleMale")
 	}
 }
 
 func TestTitleFemale(t *testing.T) {
-	p := GetPerson()
-	if !slice.Contains(titlesFemale, p.TitleFeMale()) {
+	female, err := GetPerson().TitleFeMale(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if !slice.Contains(titlesFemale, female.(string)) {
 		t.Error("Expected value from variable titleFemales in function TitleFeMale")
 	}
 }
 
 func TestFirstNameMale(t *testing.T) {
-	p := GetPerson()
-	if !slice.Contains(firstNamesMale, p.FirstNameMale()) {
+	firstName, err := GetPerson().FirstNameMale(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if !slice.Contains(firstNamesMale, firstName.(string)) {
 		t.Error("Expected value from variable firstNamesMale in function FirstNameMale")
 	}
 }
 
 func TestFirstNameFemale(t *testing.T) {
-	p := GetPerson()
-	if !slice.Contains(firstNamesFemale, p.FirstNameFemale()) {
+	firstName, err := GetPerson().FirstNameFemale(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if !slice.Contains(firstNamesFemale, firstName.(string)) {
 		t.Error("Expected value from variable firstNamesFemale in function FirstNameFemale")
 	}
 }
 
 func TestFirstName(t *testing.T) {
-	p := GetPerson()
-	if !slice.Contains(firstNames, p.FirstName()) {
+	firstname, err := GetPerson().FirstName(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if !slice.Contains(firstNames, firstname.(string)) {
 		t.Error("Expected value from either firstNamesMale or firstNamesFemale in function FirstName")
 	}
 }
 
 func TestLastName(t *testing.T) {
-	p := GetPerson()
-	if !slice.Contains(lastNames, p.LastName()) {
+	lastname, err := GetPerson().LastName(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if !slice.Contains(lastNames, lastname.(string)) {
 		t.Error("Expected value from variable lastNames in function LastName")
 	}
 }
 
 func TestNameMale(t *testing.T) {
-	p := GetPerson()
+	name, err := GetPerson().Name(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
 	randNameFlag = 51
-	if p.Name() == "" {
+	if name.(string) == "" {
 		t.Error("Expected from function name string get empty string")
 	}
 }
 func TestNameFemale(t *testing.T) {
-	p := GetPerson()
+	name, err := GetPerson().Name(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
 	randNameFlag = 20
-	if p.Name() == "" {
+	if name.(string) == "" {
 		t.Error("Expected from function name string get empty string")
 	}
 }
diff --git a/phone_test.go b/phone_test.go
index 8bc9a0a..40295f6 100644
--- a/phone_test.go
+++ b/phone_test.go
@@ -1,28 +1,37 @@
 package faker
 
 import (
+	"reflect"
 	"strings"
 	"testing"
 )
 
 func TestPhoneNumber(t *testing.T) {
-	ph := GetPhoner()
-	if strings.Count(ph.PhoneNumber(), "-") != 2 {
+	ph, err := GetPhoner().PhoneNumber(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if strings.Count(ph.(string), "-") != 2 {
 		t.Error("Expected no more than two characters '-'")
 	}
 }
 
 func TestTollFreePhoneNumber(t *testing.T) {
-	ph := GetPhoner()
-
-	if !strings.HasPrefix(ph.TollFreePhoneNumber(), "(888)") && !strings.HasPrefix(ph.TollFreePhoneNumber(), "(777)") {
+	ph, err := GetPhoner().TollFreePhoneNumber(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if !strings.HasPrefix(ph.(string), "(888)") && !strings.HasPrefix(ph.(string), "(777)") {
 		t.Error("Expected character '(888)' or (777), in function TollFreePhoneNumber")
 	}
 }
 
 func TestE164PhoneNumber(t *testing.T) {
-	ph := GetPhoner()
-	if !strings.HasPrefix(ph.E164PhoneNumber(), "+") {
+	ph, err := GetPhoner().E164PhoneNumber(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if !strings.HasPrefix(ph.(string), "+") {
 		t.Error("Expected character '(888)', in function TollFreePhoneNumber")
 	}
 }
diff --git a/price_test.go b/price_test.go
index 6ea5391..9b327f3 100644
--- a/price_test.go
+++ b/price_test.go
@@ -1,7 +1,7 @@
 package faker
 
 import (
-	"fmt"
+	"reflect"
 	"strings"
 	"testing"
 
@@ -13,17 +13,22 @@ func TestSetPrice(t *testing.T) {
 }
 
 func TestCurrency(t *testing.T) {
-	p := GetPrice()
-	fmt.Println(p.Currency())
-	if !slice.Contains(currencies, p.Currency()) {
+	p, err := GetPrice().Currency(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if !slice.Contains(currencies, p.(string)) {
 		t.Error("Expected a currency code from currencies")
 	}
 }
 
 func TestAmountWithCurrency(t *testing.T) {
-	p := GetPrice()
-	fmt.Println(p.AmountWithCurrency())
-	if !strings.Contains(p.AmountWithCurrency(), " ") {
+	p, err := GetPrice().AmountWithCurrency(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+
+	if !strings.Contains(p.(string), " ") {
 		t.Error("Expected Price currency followed by a space and it's ammount")
 	}
 }
diff --git a/uuid_test.go b/uuid_test.go
index e3ea26c..8b9d945 100644
--- a/uuid_test.go
+++ b/uuid_test.go
@@ -2,24 +2,31 @@ package faker
 
 import (
 	"fmt"
+	"reflect"
 	"regexp"
 	"testing"
 )
 
 func TestDigit(t *testing.T) {
 	p := GetIdentifier()
-	uuid := p.Digit()
-	if match, err := regexp.Match("^[a-zA-Z0-9]{32}$", []byte(uuid)); !match || err != nil {
+	uuid, err := p.Digit(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
+	if match, err := regexp.Match("^[a-zA-Z0-9]{32}$", []byte(uuid.(string))); !match || err != nil {
 		t.Errorf("Could not match the UUID format, err: %+v, match: %+v", err, match)
 	}
 }
 
 func TestHyphenated(t *testing.T) {
 	p := GetIdentifier()
-	uuid := p.Hyphenated()
+	uuid, err := p.Hyphenated(reflect.Value{})
+	if err != nil {
+		t.Error("Expected  not error, got err", err)
+	}
 	exp := "[a-zA-Z 0-9]"
 	pattern := fmt.Sprintf("^%s{8}-%s{4}-%s{4}-%s{4}-%s{12}$", exp, exp, exp, exp, exp)
-	if match, err := regexp.Match(pattern, []byte(uuid)); !match || err != nil {
+	if match, err := regexp.Match(pattern, []byte(uuid.(string))); !match || err != nil {
 		t.Errorf("Could not match the UUID hyphenated format, err: %+v, match: %+v", err, match)
 	}