dqn48247 2017-11-14 06:50
浏览 16
已采纳

测试失败,应该在其中放置JSON的空片

I am testing a piece of code, called Compile:

// Compile takes in code, and returns JSON
// bytes and an error if there was one
func Compile(in string) ([]byte, error) {
    // iterate through every line in the code
    for _, line := range strings.Split(in, "
") {
        // Divide the line into sections
        // for easier processing
        tokens := strings.Split(line, " ")
        for _, a := range availableExpressions {
            for _, b := range availableStatements {
                if tokens[1] == b {
                    // It is an expression, so
                    // calculate the value of
                    // the expression
                    var val int
                    num1, err := strconv.Atoi(tokens[0])
                    if err != nil {
                        return nil, err
                    }
                    num2, err := strconv.Atoi(tokens[1])
                    if err != nil {
                        return nil, err
                    }
                    args := []int{num1, num2}
                    switch b {
                    case "+":
                        val = args[0] + args[1]
                    case "*":
                        val = args[0] * args[1]
                    case "-":
                        val = args[0] - args[1]
                    case "/":
                        val = args[0] / args[1]
                    }
                    cmd := &Mixed{
                        isExpression: true,
                        isStatement:  false,
                        Value: &Expression{
                            Name: b,
                            // for some reason go doesn't
                            // let me put args directly
                            Arguments: []interface{}{args},
                            Value:     val,
                        }}
                    fmt.Println(cmd.Value)
                    commands = append(commands, cmd)
                } else if tokens[0] == a {
                    // argument is a statement, don't bother
                    // to evaluate the value
                    arguments := strings.Join(tokens[1:], " ")
                    cmd := &Mixed{
                        isStatement:  true,
                        isExpression: false,
                        Value: &Statement{
                            Name:      a,
                            Arguments: []interface{}{arguments},
                        }}
                    fmt.Println(cmd.Value)
                    commands = append(commands, cmd)
                }
            }
        }
    }
    gen, err := json.Marshal(commands)
    // fmt prints an empty slice
    // no matter what is in
    fmt.Println(commands)
    // empty the commands
    commands = make([]*Mixed, 0)
    if err != nil {
        return nil, err
    }
    return gen, nil
}

But when running the test:

$ cat compile_test.go
package main

import "fmt"
import "testing"

func TestCompile(t *testing.T) {
    cases := []struct {
        in  string
        out string
    }{
        {
            in:  "print \"Hello World\"",
            out: "[{\"Name\":\"print\",\"Arguments\":[\"Hello World\"]}]",
        },
        {
            in:  "print \"My name is Jack White\"",
            out: "[{\"Name\":\"print\",\"Arguments\":[\"My name is Jack White\"]}]",
        },
    }
    real_stuff, err := Compile(cases[0].in)
    if err != nil {
        fmt.Printf("error: %s
", err)
    }
    if string(real_stuff) != cases[0].out {
        fmt.Printf("got %s, expected %s
", string(real_stuff), cases[0].out)
        t.Fail()
    }
    real_stuff, err = Compile(cases[1].in)
    if err != nil {
        fmt.Printf("error: %s
", err)
    }
    if string(real_stuff) != cases[1].out {
        fmt.Printf("got %s, expected %s
", string(real_stuff), cases[1].out)
        t.Fail()
    }
}
$ go test
[]
got [], expected [{"Name":"print","Arguments":["Hello World"]}]
[]
got [], expected [{"Name":"print","Arguments":["My name is Jack White"]}]
--- FAIL: TestCompile (0.06s)

Can someone explain why the test fails and why Compile doesn't work?

  • 写回答

1条回答 默认 最新

  • douao3063 2017-11-14 13:41
    关注

    You need to debug your code logic:

    I switched:

        for _, a := range availableExpressions {
            for _, b := range availableStatements {
    

    with:

        for _, a := range availableStatements {
            for _, b := range availableExpressions {
    

    Run this:

    package main
    
    import (
        "encoding/json"
        "fmt"
        "io/ioutil"
        "strconv"
        "strings"
    )
    
    // Function not implemented yet,
    // but there for completedness
    type Function struct {
        Name      string
        Arguments []interface{}
        // A function can contain
        // both expressions and
        // statements
        Code []Mixed
    }
    
    // Mixed can be either Statement
    // or Expression
    type Mixed struct {
        isStatement  bool
        isExpression bool
        Value        interface{}
    }
    
    // Statement represents
    // statements. How a statement
    // is used is entirely up to
    // the interpreter.
    type Statement struct {
        Name      string
        Arguments []interface{}
    }
    
    // Since an Expression
    // is calculated beforehand,
    // store the value
    type Expression struct {
        Name      string
        Arguments []interface{}
        Value     interface{}
    }
    
    // commands contains commands to
    // execute later.
    // It is of type Mixed because Mixed
    // can be of type Expression or Statement
    var commands = make([]*Mixed, 0)
    
    var availableStatements = []string{
        "print",
    }
    var availableExpressions = []string{
        "+",
        "-",
        "*",
        "/",
    }
    
    // Compile takes in code, and returns JSON
    // bytes and an error if there was one
    func Compile(in string) ([]byte, error) {
        // iterate through every line in the code
        for _, line := range strings.Split(in, "
    ") {
            // Divide the line into sections
            // for easier processing
            tokens := strings.Split(line, " ")
            for _, a := range availableStatements {
                for _, b := range availableExpressions {
                    if tokens[1] == b {
                        // It is an expression, so
                        // calculate the value of
                        // the expression
                        var val int
                        num1, err := strconv.Atoi(tokens[0])
                        if err != nil {
                            return nil, err
                        }
                        num2, err := strconv.Atoi(tokens[1])
                        if err != nil {
                            return nil, err
                        }
                        args := []int{num1, num2}
                        switch b {
                        case "+":
                            val = args[0] + args[1]
                        case "*":
                            val = args[0] * args[1]
                        case "-":
                            val = args[0] - args[1]
                        case "/":
                            val = args[0] / args[1]
                        }
                        cmd := &Mixed{
                            isExpression: true,
                            isStatement:  false,
                            Value: &Expression{
                                Name: b,
                                // for some reason go doesn't
                                // let me put args directly
                                Arguments: []interface{}{args},
                                Value:     val,
                            }}
                        fmt.Println(cmd.Value)
                        commands = append(commands, cmd)
                    } else if tokens[0] == a {
                        // argument is a statement, don't bother
                        // to evaluate the value
                        arguments := strings.Join(tokens[1:], " ")
                        cmd := &Mixed{
                            isStatement:  true,
                            isExpression: false,
                            Value: &Statement{
                                Name:      a,
                                Arguments: []interface{}{arguments},
                            }}
                        fmt.Println(cmd.Value)
                        commands = append(commands, cmd)
                    }
                }
            }
        }
        gen, err := json.Marshal(commands)
        fmt.Println(commands)
        // empty the commands
        commands = make([]*Mixed, 0)
        if err != nil {
            return nil, err
        }
        return gen, nil
    }
    
    func Execute(input_file string) error {
        // open input file
        f, err := ioutil.ReadFile(input_file)
        if err != nil {
            return err
        }
        // unmarshal the JSON
        var data []*Mixed
        err = json.Unmarshal(f, data)
        if err != nil {
            return err
        }
        for _, v := range data {
            var a *Expression
            var b *Statement
            // get absolute value of v
            if v.isExpression {
                a = v.Value.(*Expression)
                b = nil
            } else if v.isStatement {
                b = v.Value.(*Statement)
                a = nil
            }
            // since the expression is
            // already calculated at compile-time,
            // don't bother evaluating
            if a != nil {
                fmt.Println(a.Value)
            }
            if b != nil {
                // on the other hand, evaluate
                // statements since they're *not*
                // evaluated at compile-time
                switch b.Name {
                case "print":
                    for _, n := range b.Arguments {
                        fmt.Printf("%v", n)
                    }
                    fmt.Printf("
    ")
                }
            }
        }
        return nil
    }
    
    func main() {
        cases := []struct {
            in  string
            out string
        }{
            {
                in:  "print \"Hello World\"",
                out: "[{\"Name\":\"print\",\"Arguments\":[\"Hello World\"]}]",
            },
            {
                in:  "print \"My name is Jack White\"",
                out: "[{\"Name\":\"print\",\"Arguments\":[\"My name is Jack White\"]}]",
            },
        }
        real_stuff, err := Compile(cases[0].in)
        if err != nil {
            fmt.Printf("error: %s
    ", err)
        }
        fmt.Println(string(real_stuff))
        if string(real_stuff) != cases[0].out {
            fmt.Printf("got %s, expected %s
    ", string(real_stuff), cases[0].out)
            //t.Fail()
        }
        real_stuff, err = Compile(cases[1].in)
        if err != nil {
            fmt.Printf("error: %s
    ", err)
        }
        fmt.Println(string(real_stuff))
        if string(real_stuff) != cases[1].out {
            fmt.Printf("got %s, expected %s
    ", string(real_stuff), cases[1].out)
            //t.Fail()
        }
    }
    

    output (go test):

    &{print ["Hello World"]}
    &{print ["Hello World"]}
    &{print ["Hello World"]}
    &{print ["Hello World"]}
    [0xc04204e3c0 0xc04204e420 0xc04204e460 0xc04204e4c0]
    got [{"Value":{"Name":"print","Arguments":["\"Hello World\""]}},{"Value":{"Name":"print","Arguments":["\"Hello World\""]}},{"Value":{"Name":"print","Arguments":["\"Hello World\""]}},{"Value":{"Name":"print","Arguments":["\"Hello World\""]}}], expected [{"Name":"print","Arguments":["Hello World"]}]
    &{print ["My name is Jack White"]}
    &{print ["My name is Jack White"]}
    &{print ["My name is Jack White"]}
    &{print ["My name is Jack White"]}
    [0xc04204e6e0 0xc04204e720 0xc04204e760 0xc04204e7c0]
    got [{"Value":{"Name":"print","Arguments":["\"My name is Jack White\""]}},{"Value":{"Name":"print","Arguments":["\"My name is Jack White\""]}},{"Value":{"Name":"print","Arguments":["\"My name is Jack White\""]}},{"Value":{"Name":"print","Arguments":["\"My name is Jack White\""]}}], expected [{"Name":"print","Arguments":["My name is Jack White"]}]
    --- FAIL: TestCompile (0.00s)
    FAIL
    exit status 1
    FAIL    ar/sogo 0.016s
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 使用C#,asp.net读取Excel文件并保存到Oracle数据库
  • ¥15 C# datagridview 单元格显示进度及值
  • ¥15 thinkphp6配合social login单点登录问题
  • ¥15 HFSS 中的 H 场图与 MATLAB 中绘制的 B1 场 部分对应不上
  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配